| @@ -3,7 +3,7 @@ Gogs - Go Git Service [ |  | ||||
| ##### Current version: 0.9.1 | |||||
| ##### Current version: 0.9.2 | |||||
| | Web | UI | Preview | | | Web | UI | Preview | | ||||
| |:-------------:|:-------:|:-------:| | |:-------------:|:-------:|:-------:| | ||||
| @@ -26,6 +26,7 @@ Hamid Feizabadi <hamidfzm AT gmail DOT com> | |||||
| Huimin Wang <wanghm2009 AT hotmail DOT co DOT jp> | Huimin Wang <wanghm2009 AT hotmail DOT co DOT jp> | ||||
| ilko <kontact-mr.k AT outlook DOT com"> | ilko <kontact-mr.k AT outlook DOT com"> | ||||
| Ilya Makarov | Ilya Makarov | ||||
| Robert Nuske <robert DOT nuske AT web DOT de> | |||||
| Robin Hübner <profan AT prfn DOT se> | Robin Hübner <profan AT prfn DOT se> | ||||
| Jamie Mansfield <dev AT jamierocks DOT uk> | Jamie Mansfield <dev AT jamierocks DOT uk> | ||||
| Jean THOMAS <contact AT tibounise DOT com> | Jean THOMAS <contact AT tibounise DOT com> | ||||
| @@ -17,7 +17,7 @@ import ( | |||||
| "github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
| ) | ) | ||||
| const APP_VER = "0.9.1.0306" | |||||
| const APP_VER = "0.9.2.0309" | |||||
| func init() { | func init() { | ||||
| runtime.GOMAXPROCS(runtime.NumCPU()) | runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
| @@ -84,13 +84,18 @@ type Action struct { | |||||
| RefName string | RefName string | ||||
| IsPrivate bool `xorm:"NOT NULL DEFAULT false"` | IsPrivate bool `xorm:"NOT NULL DEFAULT false"` | ||||
| Content string `xorm:"TEXT"` | Content string `xorm:"TEXT"` | ||||
| Created time.Time `xorm:"created"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| } | |||||
| func (a *Action) BeforeInsert() { | |||||
| a.CreatedUnix = time.Now().UTC().Unix() | |||||
| } | } | ||||
| func (a *Action) AfterSet(colName string, _ xorm.Cell) { | func (a *Action) AfterSet(colName string, _ xorm.Cell) { | ||||
| switch colName { | switch colName { | ||||
| case "created": | |||||
| a.Created = regulateTimeZone(a.Created) | |||||
| case "created_unix": | |||||
| a.Created = time.Unix(a.CreatedUnix, 0).Local() | |||||
| } | } | ||||
| } | } | ||||
| @@ -12,6 +12,7 @@ import ( | |||||
| "time" | "time" | ||||
| "github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
| "github.com/go-xorm/xorm" | |||||
| "github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
| "github.com/gogits/gogs/modules/log" | "github.com/gogits/gogs/modules/log" | ||||
| @@ -29,7 +30,19 @@ type Notice struct { | |||||
| ID int64 `xorm:"pk autoincr"` | ID int64 `xorm:"pk autoincr"` | ||||
| Type NoticeType | Type NoticeType | ||||
| Description string `xorm:"TEXT"` | Description string `xorm:"TEXT"` | ||||
| Created time.Time `xorm:"CREATED"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| } | |||||
| func (n *Notice) BeforeInsert() { | |||||
| n.CreatedUnix = time.Now().UTC().Unix() | |||||
| } | |||||
| func (n *Notice) AfterSet(colName string, _ xorm.Cell) { | |||||
| switch colName { | |||||
| case "created_unix": | |||||
| n.Created = time.Unix(n.CreatedUnix, 0).Local() | |||||
| } | |||||
| } | } | ||||
| // TrStr returns a translation format string. | // TrStr returns a translation format string. | ||||
| @@ -52,14 +52,28 @@ type Issue struct { | |||||
| RenderedContent string `xorm:"-"` | RenderedContent string `xorm:"-"` | ||||
| Priority int | Priority int | ||||
| NumComments int | NumComments int | ||||
| Deadline time.Time | |||||
| Created time.Time `xorm:"CREATED"` | |||||
| Updated time.Time `xorm:"UPDATED"` | |||||
| Deadline time.Time `xorm:"-"` | |||||
| DeadlineUnix int64 | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| Updated time.Time `xorm:"-"` | |||||
| UpdatedUnix int64 | |||||
| Attachments []*Attachment `xorm:"-"` | Attachments []*Attachment `xorm:"-"` | ||||
| Comments []*Comment `xorm:"-"` | Comments []*Comment `xorm:"-"` | ||||
| } | } | ||||
| func (i *Issue) BeforeInsert() { | |||||
| i.CreatedUnix = time.Now().UTC().Unix() | |||||
| i.UpdatedUnix = i.CreatedUnix | |||||
| } | |||||
| func (i *Issue) BeforeUpdate() { | |||||
| i.UpdatedUnix = time.Now().UTC().Unix() | |||||
| i.DeadlineUnix = i.Deadline.UTC().Unix() | |||||
| } | |||||
| func (i *Issue) AfterSet(colName string, _ xorm.Cell) { | func (i *Issue) AfterSet(colName string, _ xorm.Cell) { | ||||
| var err error | var err error | ||||
| switch colName { | switch colName { | ||||
| @@ -92,8 +106,12 @@ func (i *Issue) AfterSet(colName string, _ xorm.Cell) { | |||||
| if err != nil { | if err != nil { | ||||
| log.Error(3, "GetUserByID[%d]: %v", i.ID, err) | log.Error(3, "GetUserByID[%d]: %v", i.ID, err) | ||||
| } | } | ||||
| case "created": | |||||
| i.Created = regulateTimeZone(i.Created) | |||||
| case "deadline_unix": | |||||
| i.Deadline = time.Unix(i.DeadlineUnix, 0).Local() | |||||
| case "created_unix": | |||||
| i.Created = time.Unix(i.CreatedUnix, 0).Local() | |||||
| case "updated_unix": | |||||
| i.Updated = time.Unix(i.UpdatedUnix, 0).Local() | |||||
| } | } | ||||
| } | } | ||||
| @@ -951,12 +969,19 @@ type Milestone struct { | |||||
| IsClosed bool | IsClosed bool | ||||
| NumIssues int | NumIssues int | ||||
| NumClosedIssues int | NumClosedIssues int | ||||
| NumOpenIssues int `xorm:"-"` | |||||
| Completeness int // Percentage(1-100). | |||||
| Deadline time.Time | |||||
| DeadlineString string `xorm:"-"` | |||||
| IsOverDue bool `xorm:"-"` | |||||
| ClosedDate time.Time | |||||
| NumOpenIssues int `xorm:"-"` | |||||
| Completeness int // Percentage(1-100). | |||||
| IsOverDue bool `xorm:"-"` | |||||
| DeadlineString string `xorm:"-"` | |||||
| Deadline time.Time `xorm:"-"` | |||||
| DeadlineUnix int64 | |||||
| ClosedDate time.Time `xorm:"-"` | |||||
| ClosedDateUnix int64 | |||||
| } | |||||
| func (m *Milestone) BeforeInsert() { | |||||
| m.DeadlineUnix = m.Deadline.UTC().Unix() | |||||
| } | } | ||||
| func (m *Milestone) BeforeUpdate() { | func (m *Milestone) BeforeUpdate() { | ||||
| @@ -965,19 +990,25 @@ func (m *Milestone) BeforeUpdate() { | |||||
| } else { | } else { | ||||
| m.Completeness = 0 | m.Completeness = 0 | ||||
| } | } | ||||
| m.DeadlineUnix = m.Deadline.UTC().Unix() | |||||
| m.ClosedDateUnix = m.ClosedDate.UTC().Unix() | |||||
| } | } | ||||
| func (m *Milestone) AfterSet(colName string, _ xorm.Cell) { | func (m *Milestone) AfterSet(colName string, _ xorm.Cell) { | ||||
| if colName == "deadline" { | |||||
| switch colName { | |||||
| case "deadline_unix": | |||||
| m.Deadline = time.Unix(m.DeadlineUnix, 0).Local() | |||||
| if m.Deadline.Year() == 9999 { | if m.Deadline.Year() == 9999 { | ||||
| return | return | ||||
| } | } | ||||
| m.Deadline = regulateTimeZone(m.Deadline) | |||||
| m.DeadlineString = m.Deadline.Format("2006-01-02") | m.DeadlineString = m.Deadline.Format("2006-01-02") | ||||
| if time.Now().After(m.Deadline) { | |||||
| if time.Now().Local().After(m.Deadline) { | |||||
| m.IsOverDue = true | m.IsOverDue = true | ||||
| } | } | ||||
| case "closed_date_unix": | |||||
| m.ClosedDate = time.Unix(m.ClosedDateUnix, 0).Local() | |||||
| } | } | ||||
| } | } | ||||
| @@ -1252,7 +1283,20 @@ type Attachment struct { | |||||
| CommentID int64 | CommentID int64 | ||||
| ReleaseID int64 `xorm:"INDEX"` | ReleaseID int64 `xorm:"INDEX"` | ||||
| Name string | Name string | ||||
| Created time.Time `xorm:"CREATED"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| } | |||||
| func (a *Attachment) BeforeInsert() { | |||||
| a.CreatedUnix = time.Now().UTC().Unix() | |||||
| } | |||||
| func (a *Attachment) AfterSet(colName string, _ xorm.Cell) { | |||||
| switch colName { | |||||
| case "created_unix": | |||||
| a.Created = time.Unix(a.CreatedUnix, 0).Local() | |||||
| } | |||||
| } | } | ||||
| // AttachmentLocalPath returns where attachment is stored in local file system based on given UUID. | // AttachmentLocalPath returns where attachment is stored in local file system based on given UUID. | ||||
| @@ -52,9 +52,11 @@ type Comment struct { | |||||
| IssueID int64 `xorm:"INDEX"` | IssueID int64 `xorm:"INDEX"` | ||||
| CommitID int64 | CommitID int64 | ||||
| Line int64 | Line int64 | ||||
| Content string `xorm:"TEXT"` | |||||
| RenderedContent string `xorm:"-"` | |||||
| Created time.Time `xorm:"CREATED"` | |||||
| Content string `xorm:"TEXT"` | |||||
| RenderedContent string `xorm:"-"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| // Reference issue in commit message | // Reference issue in commit message | ||||
| CommitSHA string `xorm:"VARCHAR(40)"` | CommitSHA string `xorm:"VARCHAR(40)"` | ||||
| @@ -65,6 +67,10 @@ type Comment struct { | |||||
| ShowTag CommentTag `xorm:"-"` | ShowTag CommentTag `xorm:"-"` | ||||
| } | } | ||||
| func (c *Comment) BeforeInsert() { | |||||
| c.CreatedUnix = time.Now().UTC().Unix() | |||||
| } | |||||
| func (c *Comment) AfterSet(colName string, _ xorm.Cell) { | func (c *Comment) AfterSet(colName string, _ xorm.Cell) { | ||||
| var err error | var err error | ||||
| switch colName { | switch colName { | ||||
| @@ -84,8 +90,8 @@ func (c *Comment) AfterSet(colName string, _ xorm.Cell) { | |||||
| log.Error(3, "GetUserByID[%d]: %v", c.ID, err) | log.Error(3, "GetUserByID[%d]: %v", c.ID, err) | ||||
| } | } | ||||
| } | } | ||||
| case "created": | |||||
| c.Created = regulateTimeZone(c.Created) | |||||
| case "created_unix": | |||||
| c.Created = time.Unix(c.CreatedUnix, 0).Local() | |||||
| } | } | ||||
| } | } | ||||
| @@ -101,8 +101,20 @@ type LoginSource struct { | |||||
| Name string `xorm:"UNIQUE"` | Name string `xorm:"UNIQUE"` | ||||
| IsActived bool `xorm:"NOT NULL DEFAULT false"` | IsActived bool `xorm:"NOT NULL DEFAULT false"` | ||||
| Cfg core.Conversion `xorm:"TEXT"` | Cfg core.Conversion `xorm:"TEXT"` | ||||
| Created time.Time `xorm:"CREATED"` | |||||
| Updated time.Time `xorm:"UPDATED"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| Updated time.Time `xorm:"-"` | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (s *LoginSource) BeforeInsert() { | |||||
| s.CreatedUnix = time.Now().UTC().Unix() | |||||
| s.UpdatedUnix = s.CreatedUnix | |||||
| } | |||||
| func (s *LoginSource) BeforeUpdate() { | |||||
| s.UpdatedUnix = time.Now().UTC().Unix() | |||||
| } | } | ||||
| // Cell2Int64 converts a xorm.Cell type to int64, | // Cell2Int64 converts a xorm.Cell type to int64, | ||||
| @@ -132,6 +144,15 @@ func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { | |||||
| } | } | ||||
| } | } | ||||
| func (s *LoginSource) AfterSet(colName string, _ xorm.Cell) { | |||||
| switch colName { | |||||
| case "created_unix": | |||||
| s.Created = time.Unix(s.CreatedUnix, 0).Local() | |||||
| case "updated_unix": | |||||
| s.Updated = time.Unix(s.UpdatedUnix, 0).Local() | |||||
| } | |||||
| } | |||||
| func (source *LoginSource) TypeName() string { | func (source *LoginSource) TypeName() string { | ||||
| return LoginNames[source.Type] | return LoginNames[source.Type] | ||||
| } | } | ||||
| @@ -13,6 +13,7 @@ import ( | |||||
| "path" | "path" | ||||
| "path/filepath" | "path/filepath" | ||||
| "strings" | "strings" | ||||
| "time" | |||||
| "github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
| "github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
| @@ -65,6 +66,7 @@ var migrations = []Migration{ | |||||
| NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16 | NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16 | ||||
| NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20 | NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20 | ||||
| NewMigration("generate rands and salt for organizations", generateOrgRandsAndSalt), // V10 -> V11:v0.8.5 | NewMigration("generate rands and salt for organizations", generateOrgRandsAndSalt), // V10 -> V11:v0.8.5 | ||||
| NewMigration("convert date to unix timestamp", convertDateToUnix), // V11 -> V12:v0.9.2 | |||||
| } | } | ||||
| // Migrate database to current version | // Migrate database to current version | ||||
| @@ -453,3 +455,221 @@ func generateOrgRandsAndSalt(x *xorm.Engine) (err error) { | |||||
| return sess.Commit() | return sess.Commit() | ||||
| } | } | ||||
| type TAction struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| } | |||||
| func (t *TAction) TableName() string { return "action" } | |||||
| type TNotice struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| } | |||||
| func (t *TNotice) TableName() string { return "notice" } | |||||
| type TComment struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| } | |||||
| func (t *TComment) TableName() string { return "comment" } | |||||
| type TIssue struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| DeadlineUnix int64 | |||||
| CreatedUnix int64 | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (t *TIssue) TableName() string { return "issue" } | |||||
| type TMilestone struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| DeadlineUnix int64 | |||||
| ClosedDateUnix int64 | |||||
| } | |||||
| func (t *TMilestone) TableName() string { return "milestone" } | |||||
| type TAttachment struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| } | |||||
| func (t *TAttachment) TableName() string { return "attachment" } | |||||
| type TLoginSource struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (t *TLoginSource) TableName() string { return "login_source" } | |||||
| type TPull struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| MergedUnix int64 | |||||
| } | |||||
| func (t *TPull) TableName() string { return "pull_request" } | |||||
| type TRelease struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| } | |||||
| func (t *TRelease) TableName() string { return "release" } | |||||
| type TRepo struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (t *TRepo) TableName() string { return "repository" } | |||||
| type TMirror struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| UpdatedUnix int64 | |||||
| NextUpdateUnix int64 | |||||
| } | |||||
| func (t *TMirror) TableName() string { return "mirror" } | |||||
| type TPublicKey struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (t *TPublicKey) TableName() string { return "public_key" } | |||||
| type TDeployKey struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (t *TDeployKey) TableName() string { return "deploy_key" } | |||||
| type TAccessToken struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (t *TAccessToken) TableName() string { return "access_token" } | |||||
| type TUser struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (t *TUser) TableName() string { return "user" } | |||||
| type TWebhook struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| CreatedUnix int64 | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (t *TWebhook) TableName() string { return "webhook" } | |||||
| func convertDateToUnix(x *xorm.Engine) (err error) { | |||||
| type Bean struct { | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| Created time.Time | |||||
| Updated time.Time | |||||
| Merged time.Time | |||||
| Deadline time.Time | |||||
| ClosedDate time.Time | |||||
| NextUpdate time.Time | |||||
| } | |||||
| var tables = []struct { | |||||
| name string | |||||
| cols []string | |||||
| bean interface{} | |||||
| }{ | |||||
| {"action", []string{"created"}, new(TAction)}, | |||||
| {"notice", []string{"created"}, new(TNotice)}, | |||||
| {"comment", []string{"created"}, new(TComment)}, | |||||
| {"issue", []string{"deadline", "created", "updated"}, new(TIssue)}, | |||||
| {"milestone", []string{"deadline", "closed_date"}, new(TMilestone)}, | |||||
| {"attachment", []string{"created"}, new(TAttachment)}, | |||||
| {"login_source", []string{"created", "updated"}, new(TLoginSource)}, | |||||
| {"pull_request", []string{"merged"}, new(TPull)}, | |||||
| {"release", []string{"created"}, new(TRelease)}, | |||||
| {"repository", []string{"created", "updated"}, new(TRepo)}, | |||||
| {"mirror", []string{"updated", "next_update"}, new(TMirror)}, | |||||
| {"public_key", []string{"created", "updated"}, new(TPublicKey)}, | |||||
| {"deploy_key", []string{"created", "updated"}, new(TDeployKey)}, | |||||
| {"access_token", []string{"created", "updated"}, new(TAccessToken)}, | |||||
| {"user", []string{"created", "updated"}, new(TUser)}, | |||||
| {"webhook", []string{"created", "updated"}, new(TWebhook)}, | |||||
| } | |||||
| for _, table := range tables { | |||||
| log.Info("Converting table: %s", table.name) | |||||
| if err = x.Sync2(table.bean); err != nil { | |||||
| return fmt.Errorf("Sync [table: %s]: %v", table.name, err) | |||||
| } | |||||
| offset := 0 | |||||
| for { | |||||
| beans := make([]*Bean, 0, 100) | |||||
| if err = x.Sql(fmt.Sprintf("SELECT * FROM `%s` ORDER BY id ASC LIMIT 100 OFFSET %d", | |||||
| table.name, offset)).Find(&beans); err != nil { | |||||
| return fmt.Errorf("select beans [table: %s, offset: %d]: %v", table.name, offset, err) | |||||
| } | |||||
| log.Trace("Table [%s]: offset: %d, beans: %d", table.name, offset, len(beans)) | |||||
| if len(beans) == 0 { | |||||
| break | |||||
| } | |||||
| offset += 100 | |||||
| baseSQL := "UPDATE `" + table.name + "` SET " | |||||
| for _, bean := range beans { | |||||
| valSQLs := make([]string, 0, len(table.cols)) | |||||
| for _, col := range table.cols { | |||||
| fieldSQL := "" | |||||
| fieldSQL += col + "_unix = " | |||||
| switch col { | |||||
| case "deadline": | |||||
| if bean.Deadline.IsZero() { | |||||
| continue | |||||
| } | |||||
| fieldSQL += com.ToStr(bean.Deadline.UTC().Unix()) | |||||
| case "created": | |||||
| fieldSQL += com.ToStr(bean.Created.UTC().Unix()) | |||||
| case "updated": | |||||
| fieldSQL += com.ToStr(bean.Updated.UTC().Unix()) | |||||
| case "closed_date": | |||||
| fieldSQL += com.ToStr(bean.ClosedDate.UTC().Unix()) | |||||
| case "merged": | |||||
| fieldSQL += com.ToStr(bean.Merged.UTC().Unix()) | |||||
| case "next_update": | |||||
| fieldSQL += com.ToStr(bean.NextUpdate.UTC().Unix()) | |||||
| } | |||||
| valSQLs = append(valSQLs, fieldSQL) | |||||
| } | |||||
| if len(valSQLs) == 0 { | |||||
| continue | |||||
| } | |||||
| if _, err = x.Exec(baseSQL + strings.Join(valSQLs, ",") + " WHERE id = " + com.ToStr(bean.ID)); err != nil { | |||||
| return fmt.Errorf("update bean [table: %s, id: %d]: %v", table.name, bean.ID, err) | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @@ -11,16 +11,13 @@ import ( | |||||
| "os" | "os" | ||||
| "path" | "path" | ||||
| "strings" | "strings" | ||||
| "time" | |||||
| "github.com/Unknwon/com" | |||||
| _ "github.com/go-sql-driver/mysql" | _ "github.com/go-sql-driver/mysql" | ||||
| "github.com/go-xorm/core" | "github.com/go-xorm/core" | ||||
| "github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
| _ "github.com/lib/pq" | _ "github.com/lib/pq" | ||||
| "github.com/gogits/gogs/models/migrations" | "github.com/gogits/gogs/models/migrations" | ||||
| "github.com/gogits/gogs/modules/log" | |||||
| "github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
| ) | ) | ||||
| @@ -44,27 +41,6 @@ func sessionRelease(sess *xorm.Session) { | |||||
| sess.Close() | sess.Close() | ||||
| } | } | ||||
| // Note: get back time.Time from database Go sees it at UTC where they are really Local. | |||||
| // So this function makes correct timezone offset. | |||||
| func regulateTimeZone(t time.Time) time.Time { | |||||
| if !setting.UseMySQL { | |||||
| return t | |||||
| } | |||||
| zone := t.Local().Format("-0700") | |||||
| if len(zone) != 5 { | |||||
| log.Error(4, "Unprocessable timezone: %s - %s", t.Local(), zone) | |||||
| return t | |||||
| } | |||||
| hour := com.StrTo(zone[2:3]).MustInt() | |||||
| minutes := com.StrTo(zone[3:5]).MustInt() | |||||
| if zone[0] == '-' { | |||||
| return t.Add(time.Duration(hour) * time.Hour).Add(time.Duration(minutes) * time.Minute) | |||||
| } | |||||
| return t.Add(-1 * time.Duration(hour) * time.Hour).Add(-1 * time.Duration(minutes) * time.Minute) | |||||
| } | |||||
| var ( | var ( | ||||
| x *xorm.Engine | x *xorm.Engine | ||||
| tables []interface{} | tables []interface{} | ||||
| @@ -58,20 +58,25 @@ type PullRequest struct { | |||||
| HasMerged bool | HasMerged bool | ||||
| MergedCommitID string `xorm:"VARCHAR(40)"` | MergedCommitID string `xorm:"VARCHAR(40)"` | ||||
| Merged time.Time | |||||
| MergerID int64 | MergerID int64 | ||||
| Merger *User `xorm:"-"` | |||||
| Merger *User `xorm:"-"` | |||||
| Merged time.Time `xorm:"-"` | |||||
| MergedUnix int64 | |||||
| } | |||||
| func (pr *PullRequest) BeforeUpdate() { | |||||
| pr.MergedUnix = pr.Merged.UTC().Unix() | |||||
| } | } | ||||
| // Note: don't try to get Pull because will end up recursive querying. | // Note: don't try to get Pull because will end up recursive querying. | ||||
| func (pr *PullRequest) AfterSet(colName string, _ xorm.Cell) { | func (pr *PullRequest) AfterSet(colName string, _ xorm.Cell) { | ||||
| switch colName { | switch colName { | ||||
| case "merged": | |||||
| case "merged_unix": | |||||
| if !pr.HasMerged { | if !pr.HasMerged { | ||||
| return | return | ||||
| } | } | ||||
| pr.Merged = regulateTimeZone(pr.Merged) | |||||
| pr.Merged = time.Unix(pr.MergedUnix, 0).Local() | |||||
| } | } | ||||
| } | } | ||||
| @@ -33,13 +33,19 @@ type Release struct { | |||||
| Note string `xorm:"TEXT"` | Note string `xorm:"TEXT"` | ||||
| IsDraft bool `xorm:"NOT NULL DEFAULT false"` | IsDraft bool `xorm:"NOT NULL DEFAULT false"` | ||||
| IsPrerelease bool | IsPrerelease bool | ||||
| Created time.Time `xorm:"CREATED"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| } | |||||
| func (r *Release) BeforeInsert() { | |||||
| r.CreatedUnix = r.Created.UTC().Unix() | |||||
| } | } | ||||
| func (r *Release) AfterSet(colName string, _ xorm.Cell) { | func (r *Release) AfterSet(colName string, _ xorm.Cell) { | ||||
| switch colName { | switch colName { | ||||
| case "created": | |||||
| r.Created = regulateTimeZone(r.Created) | |||||
| case "created_unix": | |||||
| r.Created = time.Unix(r.CreatedUnix, 0).Local() | |||||
| } | } | ||||
| } | } | ||||
| @@ -178,8 +178,19 @@ type Repository struct { | |||||
| ForkID int64 | ForkID int64 | ||||
| BaseRepo *Repository `xorm:"-"` | BaseRepo *Repository `xorm:"-"` | ||||
| Created time.Time `xorm:"CREATED"` | |||||
| Updated time.Time `xorm:"UPDATED"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| Updated time.Time `xorm:"-"` | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (repo *Repository) BeforeInsert() { | |||||
| repo.CreatedUnix = time.Now().UTC().Unix() | |||||
| repo.UpdatedUnix = repo.CreatedUnix | |||||
| } | |||||
| func (repo *Repository) BeforeUpdate() { | |||||
| repo.UpdatedUnix = time.Now().UTC().Unix() | |||||
| } | } | ||||
| func (repo *Repository) AfterSet(colName string, _ xorm.Cell) { | func (repo *Repository) AfterSet(colName string, _ xorm.Cell) { | ||||
| @@ -195,8 +206,10 @@ func (repo *Repository) AfterSet(colName string, _ xorm.Cell) { | |||||
| repo.NumOpenPulls = repo.NumPulls - repo.NumClosedPulls | repo.NumOpenPulls = repo.NumPulls - repo.NumClosedPulls | ||||
| case "num_closed_milestones": | case "num_closed_milestones": | ||||
| repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones | repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones | ||||
| case "updated": | |||||
| repo.Updated = regulateTimeZone(repo.Updated) | |||||
| case "created_unix": | |||||
| repo.Created = time.Unix(repo.CreatedUnix, 0).Local() | |||||
| case "updated_unix": | |||||
| repo.Updated = time.Unix(repo.UpdatedUnix, 0) | |||||
| } | } | ||||
| } | } | ||||
| @@ -523,16 +536,28 @@ func IsUsableName(name string) error { | |||||
| // Mirror represents a mirror information of repository. | // Mirror represents a mirror information of repository. | ||||
| type Mirror struct { | type Mirror struct { | ||||
| ID int64 `xorm:"pk autoincr"` | |||||
| RepoID int64 | |||||
| Repo *Repository `xorm:"-"` | |||||
| Interval int // Hour. | |||||
| Updated time.Time `xorm:"UPDATED"` | |||||
| NextUpdate time.Time | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| RepoID int64 | |||||
| Repo *Repository `xorm:"-"` | |||||
| Interval int // Hour. | |||||
| Updated time.Time `xorm:"-"` | |||||
| UpdatedUnix int64 | |||||
| NextUpdate time.Time `xorm:"-"` | |||||
| NextUpdateUnix int64 | |||||
| address string `xorm:"-"` | address string `xorm:"-"` | ||||
| } | } | ||||
| func (m *Mirror) BeforeInsert() { | |||||
| m.NextUpdateUnix = m.NextUpdate.UTC().Unix() | |||||
| } | |||||
| func (m *Mirror) BeforeUpdate() { | |||||
| m.UpdatedUnix = time.Now().UTC().Unix() | |||||
| m.NextUpdateUnix = m.NextUpdate.UTC().Unix() | |||||
| } | |||||
| func (m *Mirror) AfterSet(colName string, _ xorm.Cell) { | func (m *Mirror) AfterSet(colName string, _ xorm.Cell) { | ||||
| var err error | var err error | ||||
| switch colName { | switch colName { | ||||
| @@ -541,6 +566,10 @@ func (m *Mirror) AfterSet(colName string, _ xorm.Cell) { | |||||
| if err != nil { | if err != nil { | ||||
| log.Error(3, "GetRepositoryByID[%d]: %v", m.ID, err) | log.Error(3, "GetRepositoryByID[%d]: %v", m.ID, err) | ||||
| } | } | ||||
| case "updated_unix": | |||||
| m.Updated = time.Unix(m.UpdatedUnix, 0).Local() | |||||
| case "next_updated_unix": | |||||
| m.NextUpdate = time.Unix(m.NextUpdateUnix, 0).Local() | |||||
| } | } | ||||
| } | } | ||||
| @@ -6,16 +6,14 @@ package models | |||||
| import ( | import ( | ||||
| "fmt" | "fmt" | ||||
| "time" | |||||
| ) | ) | ||||
| // Collaboration represent the relation between an individual and a repository. | // Collaboration represent the relation between an individual and a repository. | ||||
| type Collaboration struct { | type Collaboration struct { | ||||
| ID int64 `xorm:"pk autoincr"` | |||||
| RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
| UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
| Mode AccessMode `xorm:"DEFAULT 2 NOT NULL"` | |||||
| Created time.Time `xorm:"CREATED"` | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
| UserID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
| Mode AccessMode `xorm:"DEFAULT 2 NOT NULL"` | |||||
| } | } | ||||
| func (c *Collaboration) ModeName() string { | func (c *Collaboration) ModeName() string { | ||||
| @@ -45,22 +45,36 @@ const ( | |||||
| // PublicKey represents a SSH or deploy key. | // PublicKey represents a SSH or deploy key. | ||||
| type PublicKey struct { | type PublicKey struct { | ||||
| ID int64 `xorm:"pk autoincr"` | |||||
| OwnerID int64 `xorm:"INDEX NOT NULL"` | |||||
| Name string `xorm:"NOT NULL"` | |||||
| Fingerprint string `xorm:"NOT NULL"` | |||||
| Content string `xorm:"TEXT NOT NULL"` | |||||
| Mode AccessMode `xorm:"NOT NULL DEFAULT 2"` | |||||
| Type KeyType `xorm:"NOT NULL DEFAULT 1"` | |||||
| Created time.Time `xorm:"CREATED"` | |||||
| Updated time.Time // Note: Updated must below Created for AfterSet. | |||||
| HasRecentActivity bool `xorm:"-"` | |||||
| HasUsed bool `xorm:"-"` | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| OwnerID int64 `xorm:"INDEX NOT NULL"` | |||||
| Name string `xorm:"NOT NULL"` | |||||
| Fingerprint string `xorm:"NOT NULL"` | |||||
| Content string `xorm:"TEXT NOT NULL"` | |||||
| Mode AccessMode `xorm:"NOT NULL DEFAULT 2"` | |||||
| Type KeyType `xorm:"NOT NULL DEFAULT 1"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| Updated time.Time `xorm:"-"` // Note: Updated must below Created for AfterSet. | |||||
| UpdatedUnix int64 | |||||
| HasRecentActivity bool `xorm:"-"` | |||||
| HasUsed bool `xorm:"-"` | |||||
| } | |||||
| func (k *PublicKey) BeforeInsert() { | |||||
| k.CreatedUnix = time.Now().UTC().Unix() | |||||
| } | |||||
| func (k *PublicKey) BeforeUpdate() { | |||||
| k.UpdatedUnix = time.Now().UTC().Unix() | |||||
| } | } | ||||
| func (k *PublicKey) AfterSet(colName string, _ xorm.Cell) { | func (k *PublicKey) AfterSet(colName string, _ xorm.Cell) { | ||||
| switch colName { | switch colName { | ||||
| case "created": | |||||
| case "created_unix": | |||||
| k.Created = time.Unix(k.CreatedUnix, 0).Local() | |||||
| case "updated_unix": | |||||
| k.Updated = time.Unix(k.UpdatedUnix, 0).Local() | |||||
| k.HasUsed = k.Updated.After(k.Created) | k.HasUsed = k.Updated.After(k.Created) | ||||
| k.HasRecentActivity = k.Updated.Add(7 * 24 * time.Hour).After(time.Now()) | k.HasRecentActivity = k.Updated.Add(7 * 24 * time.Hour).After(time.Now()) | ||||
| } | } | ||||
| @@ -608,21 +622,35 @@ func RewriteAllPublicKeys() error { | |||||
| // DeployKey represents deploy key information and its relation with repository. | // DeployKey represents deploy key information and its relation with repository. | ||||
| type DeployKey struct { | type DeployKey struct { | ||||
| ID int64 `xorm:"pk autoincr"` | |||||
| KeyID int64 `xorm:"UNIQUE(s) INDEX"` | |||||
| RepoID int64 `xorm:"UNIQUE(s) INDEX"` | |||||
| Name string | |||||
| Fingerprint string | |||||
| Content string `xorm:"-"` | |||||
| Created time.Time `xorm:"CREATED"` | |||||
| Updated time.Time // Note: Updated must below Created for AfterSet. | |||||
| HasRecentActivity bool `xorm:"-"` | |||||
| HasUsed bool `xorm:"-"` | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| KeyID int64 `xorm:"UNIQUE(s) INDEX"` | |||||
| RepoID int64 `xorm:"UNIQUE(s) INDEX"` | |||||
| Name string | |||||
| Fingerprint string | |||||
| Content string `xorm:"-"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| Updated time.Time `xorm:"-"` // Note: Updated must below Created for AfterSet. | |||||
| UpdatedUnix int64 | |||||
| HasRecentActivity bool `xorm:"-"` | |||||
| HasUsed bool `xorm:"-"` | |||||
| } | |||||
| func (k *DeployKey) BeforeInsert() { | |||||
| k.CreatedUnix = time.Now().UTC().Unix() | |||||
| } | |||||
| func (k *DeployKey) BeforeUpdate() { | |||||
| k.UpdatedUnix = time.Now().UTC().Unix() | |||||
| } | } | ||||
| func (k *DeployKey) AfterSet(colName string, _ xorm.Cell) { | func (k *DeployKey) AfterSet(colName string, _ xorm.Cell) { | ||||
| switch colName { | switch colName { | ||||
| case "created": | |||||
| case "created_unix": | |||||
| k.Created = time.Unix(k.CreatedUnix, 0).Local() | |||||
| case "updated_unix": | |||||
| k.Updated = time.Unix(k.UpdatedUnix, 0).Local() | |||||
| k.HasUsed = k.Updated.After(k.Created) | k.HasUsed = k.Updated.After(k.Created) | ||||
| k.HasRecentActivity = k.Updated.Add(7 * 24 * time.Hour).After(time.Now()) | k.HasRecentActivity = k.Updated.Add(7 * 24 * time.Hour).After(time.Now()) | ||||
| } | } | ||||
| @@ -7,6 +7,7 @@ package models | |||||
| import ( | import ( | ||||
| "time" | "time" | ||||
| "github.com/go-xorm/xorm" | |||||
| gouuid "github.com/satori/go.uuid" | gouuid "github.com/satori/go.uuid" | ||||
| "github.com/gogits/gogs/modules/base" | "github.com/gogits/gogs/modules/base" | ||||
| @@ -14,16 +15,38 @@ import ( | |||||
| // AccessToken represents a personal access token. | // AccessToken represents a personal access token. | ||||
| type AccessToken struct { | type AccessToken struct { | ||||
| ID int64 `xorm:"pk autoincr"` | |||||
| UID int64 `xorm:"INDEX"` | |||||
| Name string | |||||
| Sha1 string `xorm:"UNIQUE VARCHAR(40)"` | |||||
| Created time.Time `xorm:"CREATED"` | |||||
| Updated time.Time | |||||
| ID int64 `xorm:"pk autoincr"` | |||||
| UID int64 `xorm:"INDEX"` | |||||
| Name string | |||||
| Sha1 string `xorm:"UNIQUE VARCHAR(40)"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| Updated time.Time `xorm:"-"` // Note: Updated must below Created for AfterSet. | |||||
| UpdatedUnix int64 | |||||
| HasRecentActivity bool `xorm:"-"` | HasRecentActivity bool `xorm:"-"` | ||||
| HasUsed bool `xorm:"-"` | HasUsed bool `xorm:"-"` | ||||
| } | } | ||||
| func (t *AccessToken) BeforeInsert() { | |||||
| t.CreatedUnix = time.Now().UTC().Unix() | |||||
| } | |||||
| func (t *AccessToken) BeforeUpdate() { | |||||
| t.UpdatedUnix = time.Now().UTC().Unix() | |||||
| } | |||||
| func (t *AccessToken) AfterSet(colName string, _ xorm.Cell) { | |||||
| switch colName { | |||||
| case "created_unix": | |||||
| t.Created = time.Unix(t.CreatedUnix, 0).Local() | |||||
| case "updated_unix": | |||||
| t.Updated = time.Unix(t.UpdatedUnix, 0).Local() | |||||
| t.HasUsed = t.Updated.After(t.Created) | |||||
| t.HasRecentActivity = t.Updated.Add(7 * 24 * time.Hour).After(time.Now()) | |||||
| } | |||||
| } | |||||
| // NewAccessToken creates new access token. | // NewAccessToken creates new access token. | ||||
| func NewAccessToken(t *AccessToken) error { | func NewAccessToken(t *AccessToken) error { | ||||
| t.Sha1 = base.EncodeSha1(gouuid.NewV4().String()) | t.Sha1 = base.EncodeSha1(gouuid.NewV4().String()) | ||||
| @@ -46,16 +69,7 @@ func GetAccessTokenBySHA(sha string) (*AccessToken, error) { | |||||
| // ListAccessTokens returns a list of access tokens belongs to given user. | // ListAccessTokens returns a list of access tokens belongs to given user. | ||||
| func ListAccessTokens(uid int64) ([]*AccessToken, error) { | func ListAccessTokens(uid int64) ([]*AccessToken, error) { | ||||
| tokens := make([]*AccessToken, 0, 5) | tokens := make([]*AccessToken, 0, 5) | ||||
| err := x.Where("uid=?", uid).Desc("id").Find(&tokens) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| for _, t := range tokens { | |||||
| t.HasUsed = t.Updated.After(t.Created) | |||||
| t.HasRecentActivity = t.Updated.Add(7 * 24 * time.Hour).After(time.Now()) | |||||
| } | |||||
| return tokens, nil | |||||
| return tokens, x.Where("uid=?", uid).Desc("id").Find(&tokens) | |||||
| } | } | ||||
| // UpdateAccessToken updates information of access token. | // UpdateAccessToken updates information of access token. | ||||
| @@ -68,10 +68,13 @@ type User struct { | |||||
| Repos []*Repository `xorm:"-"` | Repos []*Repository `xorm:"-"` | ||||
| Location string | Location string | ||||
| Website string | Website string | ||||
| Rands string `xorm:"VARCHAR(10)"` | |||||
| Salt string `xorm:"VARCHAR(10)"` | |||||
| Created time.Time `xorm:"CREATED"` | |||||
| Updated time.Time `xorm:"UPDATED"` | |||||
| Rands string `xorm:"VARCHAR(10)"` | |||||
| Salt string `xorm:"VARCHAR(10)"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| Updated time.Time `xorm:"-"` | |||||
| UpdatedUnix int64 | |||||
| // Remember visibility choice for convenience, true for private | // Remember visibility choice for convenience, true for private | ||||
| LastRepoVisibility bool | LastRepoVisibility bool | ||||
| @@ -103,18 +106,26 @@ type User struct { | |||||
| Members []*User `xorm:"-"` | Members []*User `xorm:"-"` | ||||
| } | } | ||||
| func (u *User) BeforeInsert() { | |||||
| u.CreatedUnix = time.Now().UTC().Unix() | |||||
| u.UpdatedUnix = u.CreatedUnix | |||||
| } | |||||
| func (u *User) BeforeUpdate() { | func (u *User) BeforeUpdate() { | ||||
| if u.MaxRepoCreation < -1 { | if u.MaxRepoCreation < -1 { | ||||
| u.MaxRepoCreation = -1 | u.MaxRepoCreation = -1 | ||||
| } | } | ||||
| u.UpdatedUnix = time.Now().UTC().Unix() | |||||
| } | } | ||||
| func (u *User) AfterSet(colName string, _ xorm.Cell) { | func (u *User) AfterSet(colName string, _ xorm.Cell) { | ||||
| switch colName { | switch colName { | ||||
| case "full_name": | case "full_name": | ||||
| u.FullName = markdown.Sanitizer.Sanitize(u.FullName) | u.FullName = markdown.Sanitizer.Sanitize(u.FullName) | ||||
| case "created": | |||||
| u.Created = regulateTimeZone(u.Created) | |||||
| case "created_unix": | |||||
| u.Created = time.Unix(u.CreatedUnix, 0).Local() | |||||
| case "updated_unix": | |||||
| u.Updated = time.Unix(u.UpdatedUnix, 0).Local() | |||||
| } | } | ||||
| } | } | ||||
| @@ -94,8 +94,20 @@ type Webhook struct { | |||||
| HookTaskType HookTaskType | HookTaskType HookTaskType | ||||
| Meta string `xorm:"TEXT"` // store hook-specific attributes | Meta string `xorm:"TEXT"` // store hook-specific attributes | ||||
| LastStatus HookStatus // Last delivery status | LastStatus HookStatus // Last delivery status | ||||
| Created time.Time `xorm:"CREATED"` | |||||
| Updated time.Time `xorm:"UPDATED"` | |||||
| Created time.Time `xorm:"-"` | |||||
| CreatedUnix int64 | |||||
| Updated time.Time `xorm:"-"` | |||||
| UpdatedUnix int64 | |||||
| } | |||||
| func (w *Webhook) BeforeInsert() { | |||||
| w.CreatedUnix = time.Now().UTC().Unix() | |||||
| w.UpdatedUnix = w.CreatedUnix | |||||
| } | |||||
| func (w *Webhook) BeforeUpdate() { | |||||
| w.UpdatedUnix = time.Now().UTC().Unix() | |||||
| } | } | ||||
| func (w *Webhook) AfterSet(colName string, _ xorm.Cell) { | func (w *Webhook) AfterSet(colName string, _ xorm.Cell) { | ||||
| @@ -106,8 +118,10 @@ func (w *Webhook) AfterSet(colName string, _ xorm.Cell) { | |||||
| if err = json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil { | if err = json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil { | ||||
| log.Error(3, "Unmarshal[%d]: %v", w.ID, err) | log.Error(3, "Unmarshal[%d]: %v", w.ID, err) | ||||
| } | } | ||||
| case "created": | |||||
| w.Created = regulateTimeZone(w.Created) | |||||
| case "created_unix": | |||||
| w.Created = time.Unix(w.CreatedUnix, 0).Local() | |||||
| case "updated_unix": | |||||
| w.Updated = time.Unix(w.UpdatedUnix, 0).Local() | |||||
| } | } | ||||
| } | } | ||||
| @@ -1 +1 @@ | |||||
| 0.9.1.0306 | |||||
| 0.9.2.0309 | |||||