* display ui time with customize time location * fix lint * rename UILocation to DefaultUILocation * move time related functions to modules/timeutil * fix tests * fix tests * fix build * fix swaggertags/v1.10.0-rc1
; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano | ; Special supported values are ANSIC, UnixDate, RubyDate, RFC822, RFC822Z, RFC850, RFC1123, RFC1123Z, RFC3339, RFC3339Nano, Kitchen, Stamp, StampMilli, StampMicro and StampNano | ||||
; For more information about the format see http://golang.org/pkg/time/#pkg-constants | ; For more information about the format see http://golang.org/pkg/time/#pkg-constants | ||||
FORMAT = | FORMAT = | ||||
; Location the UI time display i.e. Asia/Shanghai | |||||
; Empty means server's location setting | |||||
DEFAULT_UI_LOCATION = | |||||
[log] | [log] | ||||
ROOT_PATH = | ROOT_PATH = |
- `GITEA_PREFIX_SRC`, which contains the current URL prefix in the `src` path tree. To be used as prefix for links. | - `GITEA_PREFIX_SRC`, which contains the current URL prefix in the `src` path tree. To be used as prefix for links. | ||||
- `GITEA_PREFIX_RAW`, which contains the current URL prefix in the `raw` path tree. To be used as prefix for image paths. | - `GITEA_PREFIX_RAW`, which contains the current URL prefix in the `raw` path tree. To be used as prefix for image paths. | ||||
## Time (`time`) | |||||
- `FORMAT`: Time format to diplay on UI. i.e. RFC1123 or 2006-01-02 15:04:05 | |||||
- `DEFAULT_UI_LOCATION`: Default location of time on the UI, so that we can display correct user's time on UI. i.e. Shanghai/Asia | |||||
## Other (`other`) | ## Other (`other`) | ||||
- `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer. | - `SHOW_FOOTER_BRANDING`: **false**: Show Gitea branding in the footer. | ||||
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea version information in the footer. | - `SHOW_FOOTER_VERSION`: **true**: Show Gitea version information in the footer. | ||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer. | |||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer. |
- RENDER_COMMAND: 工具的命令行命令及参数。 | - RENDER_COMMAND: 工具的命令行命令及参数。 | ||||
- IS_INPUT_FILE: 输入方式是最后一个参数为文件路径还是从标准输入读取。 | - IS_INPUT_FILE: 输入方式是最后一个参数为文件路径还是从标准输入读取。 | ||||
## Time (`time`) | |||||
- `FORMAT`: 显示在界面上的时间格式。比如: RFC1123 或者 2006-01-02 15:04:05 | |||||
- `DEFAULT_UI_LOCATION`: 默认显示在界面上的时区,默认为本地时区。比如: Asia/Shanghai | |||||
## Other (`other`) | ## Other (`other`) | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"xorm.io/builder" | "xorm.io/builder" | ||||
Comment *Comment `xorm:"-"` | Comment *Comment `xorm:"-"` | ||||
IsDeleted bool `xorm:"INDEX NOT NULL DEFAULT false"` | IsDeleted bool `xorm:"INDEX NOT NULL DEFAULT false"` | ||||
RefName string | RefName string | ||||
IsPrivate bool `xorm:"INDEX NOT NULL DEFAULT false"` | |||||
Content string `xorm:"TEXT"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
IsPrivate bool `xorm:"INDEX NOT NULL DEFAULT false"` | |||||
Content string `xorm:"TEXT"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
} | } | ||||
// GetOpType gets the ActionType of this action. | // GetOpType gets the ActionType of this action. |
"os" | "os" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
) | ) | ||||
type Notice struct { | type Notice struct { | ||||
ID int64 `xorm:"pk autoincr"` | ID int64 `xorm:"pk autoincr"` | ||||
Type NoticeType | Type NoticeType | ||||
Description string `xorm:"TEXT"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
Description string `xorm:"TEXT"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
} | } | ||||
// TrStr returns a translation format string. | // TrStr returns a translation format string. |
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
gouuid "github.com/satori/go.uuid" | gouuid "github.com/satori/go.uuid" | ||||
UploaderID int64 `xorm:"INDEX DEFAULT 0"` // Notice: will be zero before this column added | UploaderID int64 `xorm:"INDEX DEFAULT 0"` // Notice: will be zero before this column added | ||||
CommentID int64 | CommentID int64 | ||||
Name string | Name string | ||||
DownloadCount int64 `xorm:"DEFAULT 0"` | |||||
Size int64 `xorm:"DEFAULT 0"` | |||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
DownloadCount int64 `xorm:"DEFAULT 0"` | |||||
Size int64 `xorm:"DEFAULT 0"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
} | } | ||||
// IncreaseDownloadCount is update download count + 1 | // IncreaseDownloadCount is update download count + 1 |
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
BranchName string `xorm:"UNIQUE(s)"` | BranchName string `xorm:"UNIQUE(s)"` | ||||
CanPush bool `xorm:"NOT NULL DEFAULT false"` | CanPush bool `xorm:"NOT NULL DEFAULT false"` | ||||
EnableWhitelist bool | EnableWhitelist bool | ||||
WhitelistUserIDs []int64 `xorm:"JSON TEXT"` | |||||
WhitelistTeamIDs []int64 `xorm:"JSON TEXT"` | |||||
EnableMergeWhitelist bool `xorm:"NOT NULL DEFAULT false"` | |||||
MergeWhitelistUserIDs []int64 `xorm:"JSON TEXT"` | |||||
MergeWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` | |||||
ApprovalsWhitelistUserIDs []int64 `xorm:"JSON TEXT"` | |||||
ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` | |||||
RequiredApprovals int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"updated"` | |||||
WhitelistUserIDs []int64 `xorm:"JSON TEXT"` | |||||
WhitelistTeamIDs []int64 `xorm:"JSON TEXT"` | |||||
EnableMergeWhitelist bool `xorm:"NOT NULL DEFAULT false"` | |||||
MergeWhitelistUserIDs []int64 `xorm:"JSON TEXT"` | |||||
MergeWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` | |||||
ApprovalsWhitelistUserIDs []int64 `xorm:"JSON TEXT"` | |||||
ApprovalsWhitelistTeamIDs []int64 `xorm:"JSON TEXT"` | |||||
RequiredApprovals int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||||
} | } | ||||
// IsProtected returns if the branch is protected | // IsProtected returns if the branch is protected | ||||
// DeletedBranch struct | // DeletedBranch struct | ||||
type DeletedBranch struct { | type DeletedBranch struct { | ||||
ID int64 `xorm:"pk autoincr"` | |||||
RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
Name string `xorm:"UNIQUE(s) NOT NULL"` | |||||
Commit string `xorm:"UNIQUE(s) NOT NULL"` | |||||
DeletedByID int64 `xorm:"INDEX"` | |||||
DeletedBy *User `xorm:"-"` | |||||
DeletedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
ID int64 `xorm:"pk autoincr"` | |||||
RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
Name string `xorm:"UNIQUE(s) NOT NULL"` | |||||
Commit string `xorm:"UNIQUE(s) NOT NULL"` | |||||
DeletedByID int64 `xorm:"INDEX"` | |||||
DeletedBy *User `xorm:"-"` | |||||
DeletedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
} | } | ||||
// AddDeletedBranch adds a deleted branch to the database | // AddDeletedBranch adds a deleted branch to the database |
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
) | ) | ||||
Creator *User `xorm:"-"` | Creator *User `xorm:"-"` | ||||
CreatorID int64 | CreatorID int64 | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
func (status *CommitStatus) loadRepo(e Engine) (err error) { | func (status *CommitStatus) loadRepo(e Engine) (err error) { |
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
"github.com/keybase/go-crypto/openpgp" | "github.com/keybase/go-crypto/openpgp" | ||||
// GPGKey represents a GPG key. | // GPGKey represents a GPG key. | ||||
type GPGKey struct { | type GPGKey struct { | ||||
ID int64 `xorm:"pk autoincr"` | |||||
OwnerID int64 `xorm:"INDEX NOT NULL"` | |||||
KeyID string `xorm:"INDEX CHAR(16) NOT NULL"` | |||||
PrimaryKeyID string `xorm:"CHAR(16)"` | |||||
Content string `xorm:"TEXT NOT NULL"` | |||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
ExpiredUnix util.TimeStamp | |||||
AddedUnix util.TimeStamp | |||||
ID int64 `xorm:"pk autoincr"` | |||||
OwnerID int64 `xorm:"INDEX NOT NULL"` | |||||
KeyID string `xorm:"INDEX CHAR(16) NOT NULL"` | |||||
PrimaryKeyID string `xorm:"CHAR(16)"` | |||||
Content string `xorm:"TEXT NOT NULL"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
ExpiredUnix timeutil.TimeStamp | |||||
AddedUnix timeutil.TimeStamp | |||||
SubsKey []*GPGKey `xorm:"-"` | SubsKey []*GPGKey `xorm:"-"` | ||||
Emails []*EmailAddress | Emails []*EmailAddress | ||||
CanSign bool | CanSign bool | ||||
// BeforeInsert will be invoked by XORM before inserting a record | // BeforeInsert will be invoked by XORM before inserting a record | ||||
func (key *GPGKey) BeforeInsert() { | func (key *GPGKey) BeforeInsert() { | ||||
key.AddedUnix = util.TimeStampNow() | |||||
key.AddedUnix = timeutil.TimeStampNow() | |||||
} | } | ||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object. | // AfterLoad is invoked from XORM after setting the values of all fields of this object. | ||||
KeyID: pubkey.KeyIdString(), | KeyID: pubkey.KeyIdString(), | ||||
PrimaryKeyID: primaryID, | PrimaryKeyID: primaryID, | ||||
Content: content, | Content: content, | ||||
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()), | |||||
ExpiredUnix: util.TimeStamp(expiry.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(pubkey.CreationTime.Unix()), | |||||
ExpiredUnix: timeutil.TimeStamp(expiry.Unix()), | |||||
CanSign: pubkey.CanSign(), | CanSign: pubkey.CanSign(), | ||||
CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(), | CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(), | ||||
CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(), | CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(), | ||||
KeyID: pubkey.KeyIdString(), | KeyID: pubkey.KeyIdString(), | ||||
PrimaryKeyID: "", | PrimaryKeyID: "", | ||||
Content: content, | Content: content, | ||||
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()), | |||||
ExpiredUnix: util.TimeStamp(expiry.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(pubkey.CreationTime.Unix()), | |||||
ExpiredUnix: timeutil.TimeStamp(expiry.Unix()), | |||||
Emails: emails, | Emails: emails, | ||||
SubsKey: subkeys, | SubsKey: subkeys, | ||||
CanSign: pubkey.CanSign(), | CanSign: pubkey.CanSign(), |
"testing" | "testing" | ||||
"time" | "time" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/stretchr/testify/assert" | "github.com/stretchr/testify/assert" | ||||
) | ) | ||||
key := &GPGKey{ | key := &GPGKey{ | ||||
KeyID: pubkey.KeyIdString(), | KeyID: pubkey.KeyIdString(), | ||||
Content: content, | Content: content, | ||||
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(pubkey.CreationTime.Unix()), | |||||
CanSign: pubkey.CanSign(), | CanSign: pubkey.CanSign(), | ||||
CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(), | CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(), | ||||
CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(), | CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(), | ||||
cannotsignkey := &GPGKey{ | cannotsignkey := &GPGKey{ | ||||
KeyID: pubkey.KeyIdString(), | KeyID: pubkey.KeyIdString(), | ||||
Content: content, | Content: content, | ||||
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(pubkey.CreationTime.Unix()), | |||||
CanSign: false, | CanSign: false, | ||||
CanEncryptComms: false, | CanEncryptComms: false, | ||||
CanEncryptStorage: false, | CanEncryptStorage: false, |
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
NumComments int | NumComments int | ||||
Ref string | Ref string | ||||
DeadlineUnix util.TimeStamp `xorm:"INDEX"` | |||||
DeadlineUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
ClosedUnix util.TimeStamp `xorm:"INDEX"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
ClosedUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
Attachments []*Attachment `xorm:"-"` | Attachments []*Attachment `xorm:"-"` | ||||
Comments []*Comment `xorm:"-"` | Comments []*Comment `xorm:"-"` | ||||
// IsOverdue checks if the issue is overdue | // IsOverdue checks if the issue is overdue | ||||
func (issue *Issue) IsOverdue() bool { | func (issue *Issue) IsOverdue() bool { | ||||
return util.TimeStampNow() >= issue.DeadlineUnix | |||||
return timeutil.TimeStampNow() >= issue.DeadlineUnix | |||||
} | } | ||||
// LoadRepo loads issue's repository | // LoadRepo loads issue's repository | ||||
issue.IsClosed = isClosed | issue.IsClosed = isClosed | ||||
if isClosed { | if isClosed { | ||||
issue.ClosedUnix = util.TimeStampNow() | |||||
issue.ClosedUnix = timeutil.TimeStampNow() | |||||
} else { | } else { | ||||
issue.ClosedUnix = 0 | issue.ClosedUnix = 0 | ||||
} | } | ||||
} | } | ||||
// GetLastEventTimestamp returns the last user visible event timestamp, either the creation of this issue or the close. | // GetLastEventTimestamp returns the last user visible event timestamp, either the creation of this issue or the close. | ||||
func (issue *Issue) GetLastEventTimestamp() util.TimeStamp { | |||||
func (issue *Issue) GetLastEventTimestamp() timeutil.TimeStamp { | |||||
if issue.IsClosed { | if issue.IsClosed { | ||||
return issue.ClosedUnix | return issue.ClosedUnix | ||||
} | } | ||||
} | } | ||||
// UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it. | // UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it. | ||||
func UpdateIssueDeadline(issue *Issue, deadlineUnix util.TimeStamp, doer *User) (err error) { | |||||
func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *User) (err error) { | |||||
// if the deadline hasn't changed do nothing | // if the deadline hasn't changed do nothing | ||||
if issue.DeadlineUnix == deadlineUnix { | if issue.DeadlineUnix == deadlineUnix { |
"strings" | "strings" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/markup" | |||||
"code.gitea.io/gitea/modules/markup/markdown" | "code.gitea.io/gitea/modules/markup/markdown" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
"xorm.io/builder" | "xorm.io/builder" | ||||
api "code.gitea.io/gitea/modules/structs" | |||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/markup" | |||||
"code.gitea.io/gitea/modules/util" | |||||
) | ) | ||||
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference. | // CommentType defines whether a comment is just a simple comment, an action (like close) or a reference. | ||||
// Path represents the 4 lines of code cemented by this comment | // Path represents the 4 lines of code cemented by this comment | ||||
Patch string `xorm:"TEXT"` | Patch string `xorm:"TEXT"` | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
// Reference issue in commit message | // Reference issue in commit message | ||||
CommitSHA string `xorm:"VARCHAR(40)"` | CommitSHA string `xorm:"VARCHAR(40)"` | ||||
}) | }) | ||||
} | } | ||||
func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlineUnix util.TimeStamp) (*Comment, error) { | |||||
func createDeadlineComment(e *xorm.Session, doer *User, issue *Issue, newDeadlineUnix timeutil.TimeStamp) (*Comment, error) { | |||||
var content string | var content string | ||||
var commentType CommentType | var commentType CommentType |
import ( | import ( | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// IssueDependency represents an issue dependency | // IssueDependency represents an issue dependency | ||||
type IssueDependency struct { | type IssueDependency struct { | ||||
ID int64 `xorm:"pk autoincr"` | |||||
UserID int64 `xorm:"NOT NULL"` | |||||
IssueID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"` | |||||
DependencyID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"` | |||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"updated"` | |||||
ID int64 `xorm:"pk autoincr"` | |||||
UserID int64 `xorm:"NOT NULL"` | |||||
IssueID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"` | |||||
DependencyID int64 `xorm:"UNIQUE(issue_dependency) NOT NULL"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||||
} | } | ||||
// DependencyType Defines Dependency Type Constants | // DependencyType Defines Dependency Type Constants |
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
) | ) | ||||
IsOverdue bool `xorm:"-"` | IsOverdue bool `xorm:"-"` | ||||
DeadlineString string `xorm:"-"` | DeadlineString string `xorm:"-"` | ||||
DeadlineUnix util.TimeStamp | |||||
ClosedDateUnix util.TimeStamp | |||||
DeadlineUnix timeutil.TimeStamp | |||||
ClosedDateUnix timeutil.TimeStamp | |||||
TotalTrackedTime int64 `xorm:"-"` | TotalTrackedTime int64 `xorm:"-"` | ||||
} | } | ||||
} | } | ||||
m.DeadlineString = m.DeadlineUnix.Format("2006-01-02") | m.DeadlineString = m.DeadlineUnix.Format("2006-01-02") | ||||
if util.TimeStampNow() >= m.DeadlineUnix { | |||||
if timeutil.TimeStampNow() >= m.DeadlineUnix { | |||||
m.IsOverdue = true | m.IsOverdue = true | ||||
} | } | ||||
} | } |
"time" | "time" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/stretchr/testify/assert" | "github.com/stretchr/testify/assert" | ||||
) | ) | ||||
IsClosed: false, | IsClosed: false, | ||||
NumOpenIssues: 5, | NumOpenIssues: 5, | ||||
NumClosedIssues: 6, | NumClosedIssues: 6, | ||||
DeadlineUnix: util.TimeStamp(time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC).Unix()), | |||||
DeadlineUnix: timeutil.TimeStamp(time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC).Unix()), | |||||
} | } | ||||
assert.Equal(t, api.Milestone{ | assert.Equal(t, api.Milestone{ | ||||
ID: milestone.ID, | ID: milestone.ID, | ||||
"is_closed=0").(*Issue) | "is_closed=0").(*Issue) | ||||
issue.IsClosed = true | issue.IsClosed = true | ||||
issue.ClosedUnix = util.TimeStampNow() | |||||
issue.ClosedUnix = timeutil.TimeStampNow() | |||||
_, err := x.Cols("is_closed", "closed_unix").Update(issue) | _, err := x.Cols("is_closed", "closed_unix").Update(issue) | ||||
assert.NoError(t, err) | assert.NoError(t, err) | ||||
assert.NoError(t, changeMilestoneIssueStats(x.NewSession(), issue)) | assert.NoError(t, changeMilestoneIssueStats(x.NewSession(), issue)) |
"fmt" | "fmt" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
"xorm.io/builder" | "xorm.io/builder" | ||||
// Reaction represents a reactions on issues and comments. | // Reaction represents a reactions on issues and comments. | ||||
type Reaction struct { | type Reaction struct { | ||||
ID int64 `xorm:"pk autoincr"` | |||||
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"` | |||||
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"` | |||||
CommentID int64 `xorm:"INDEX UNIQUE(s)"` | |||||
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"` | |||||
User *User `xorm:"-"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
ID int64 `xorm:"pk autoincr"` | |||||
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"` | |||||
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"` | |||||
CommentID int64 `xorm:"INDEX UNIQUE(s)"` | |||||
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"` | |||||
User *User `xorm:"-"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
} | } | ||||
// FindReactionsOptions describes the conditions to Find reactions | // FindReactionsOptions describes the conditions to Find reactions |
"fmt" | "fmt" | ||||
"time" | "time" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// Stopwatch represents a stopwatch for time tracking. | // Stopwatch represents a stopwatch for time tracking. | ||||
type Stopwatch struct { | type Stopwatch struct { | ||||
ID int64 `xorm:"pk autoincr"` | |||||
IssueID int64 `xorm:"INDEX"` | |||||
UserID int64 `xorm:"INDEX"` | |||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
ID int64 `xorm:"pk autoincr"` | |||||
IssueID int64 `xorm:"INDEX"` | |||||
UserID int64 `xorm:"INDEX"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
} | } | ||||
func getStopwatch(e Engine, userID, issueID int64) (sw *Stopwatch, exists bool, err error) { | func getStopwatch(e Engine, userID, issueID int64) (sw *Stopwatch, exists bool, err error) { |
import ( | import ( | ||||
"testing" | "testing" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/stretchr/testify/assert" | "github.com/stretchr/testify/assert" | ||||
) | ) | ||||
assert.NoError(t, CreateOrStopIssueStopwatch(user3, issue1)) | assert.NoError(t, CreateOrStopIssueStopwatch(user3, issue1)) | ||||
sw := AssertExistsAndLoadBean(t, &Stopwatch{UserID: 3, IssueID: 1}).(*Stopwatch) | sw := AssertExistsAndLoadBean(t, &Stopwatch{UserID: 3, IssueID: 1}).(*Stopwatch) | ||||
assert.Equal(t, true, sw.CreatedUnix <= util.TimeStampNow()) | |||||
assert.Equal(t, true, sw.CreatedUnix <= timeutil.TimeStampNow()) | |||||
assert.NoError(t, CreateOrStopIssueStopwatch(user2, issue2)) | assert.NoError(t, CreateOrStopIssueStopwatch(user2, issue2)) | ||||
AssertNotExistsBean(t, &Stopwatch{UserID: 2, IssueID: 2}) | AssertNotExistsBean(t, &Stopwatch{UserID: 2, IssueID: 2}) |
// AfterLoad is invoked from XORM after setting the values of all fields of this object. | // AfterLoad is invoked from XORM after setting the values of all fields of this object. | ||||
func (t *TrackedTime) AfterLoad() { | func (t *TrackedTime) AfterLoad() { | ||||
t.Created = time.Unix(t.CreatedUnix, 0).In(setting.UILocation) | |||||
t.Created = time.Unix(t.CreatedUnix, 0).In(setting.DefaultUILocation) | |||||
} | } | ||||
// APIFormat converts TrackedTime to API format | // APIFormat converts TrackedTime to API format |
package models | package models | ||||
import "code.gitea.io/gitea/modules/util" | |||||
import "code.gitea.io/gitea/modules/timeutil" | |||||
// IssueWatch is connection request for receiving issue notification. | // IssueWatch is connection request for receiving issue notification. | ||||
type IssueWatch struct { | type IssueWatch struct { | ||||
ID int64 `xorm:"pk autoincr"` | |||||
UserID int64 `xorm:"UNIQUE(watch) NOT NULL"` | |||||
IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"` | |||||
IsWatching bool `xorm:"NOT NULL"` | |||||
CreatedUnix util.TimeStamp `xorm:"created NOT NULL"` | |||||
UpdatedUnix util.TimeStamp `xorm:"updated NOT NULL"` | |||||
ID int64 `xorm:"pk autoincr"` | |||||
UserID int64 `xorm:"UNIQUE(watch) NOT NULL"` | |||||
IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"` | |||||
IsWatching bool `xorm:"NOT NULL"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL"` | |||||
} | } | ||||
// CreateOrUpdateIssueWatch set watching for a user and issue | // CreateOrUpdateIssueWatch set watching for a user and issue |
"fmt" | "fmt" | ||||
"io" | "io" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// LFSMetaObject stores metadata for LFS tracked files. | // LFSMetaObject stores metadata for LFS tracked files. | ||||
type LFSMetaObject struct { | type LFSMetaObject struct { | ||||
ID int64 `xorm:"pk autoincr"` | |||||
Oid string `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
Size int64 `xorm:"NOT NULL"` | |||||
RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
Existing bool `xorm:"-"` | |||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
ID int64 `xorm:"pk autoincr"` | |||||
Oid string `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
Size int64 `xorm:"NOT NULL"` | |||||
RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
Existing bool `xorm:"-"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
} | } | ||||
// Pointer returns the string representation of an LFS pointer file | // Pointer returns the string representation of an LFS pointer file |
"regexp" | "regexp" | ||||
"strings" | "strings" | ||||
"github.com/Unknwon/com" | |||||
"github.com/go-xorm/xorm" | |||||
"xorm.io/core" | |||||
"code.gitea.io/gitea/modules/auth/ldap" | "code.gitea.io/gitea/modules/auth/ldap" | ||||
"code.gitea.io/gitea/modules/auth/oauth2" | "code.gitea.io/gitea/modules/auth/oauth2" | ||||
"code.gitea.io/gitea/modules/auth/pam" | "code.gitea.io/gitea/modules/auth/pam" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | |||||
"github.com/go-xorm/xorm" | |||||
"xorm.io/core" | |||||
) | ) | ||||
// LoginType represents an login type. | // LoginType represents an login type. | ||||
IsSyncEnabled bool `xorm:"INDEX NOT NULL DEFAULT false"` | IsSyncEnabled bool `xorm:"INDEX NOT NULL DEFAULT false"` | ||||
Cfg core.Conversion `xorm:"TEXT"` | Cfg core.Conversion `xorm:"TEXT"` | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
// Cell2Int64 converts a xorm.Cell type to int64, | // Cell2Int64 converts a xorm.Cell type to int64, |
"code.gitea.io/gitea/modules/markup" | "code.gitea.io/gitea/modules/markup" | ||||
"code.gitea.io/gitea/modules/markup/markdown" | "code.gitea.io/gitea/modules/markup/markdown" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"gopkg.in/gomail.v2" | "gopkg.in/gomail.v2" | ||||
) | ) | ||||
func SendUserMail(language string, u *User, tpl base.TplName, code, subject, info string) { | func SendUserMail(language string, u *User, tpl base.TplName, code, subject, info string) { | ||||
data := map[string]interface{}{ | data := map[string]interface{}{ | ||||
"DisplayName": u.DisplayName(), | "DisplayName": u.DisplayName(), | ||||
"ActiveCodeLives": base.MinutesToFriendly(setting.Service.ActiveCodeLives, language), | |||||
"ResetPwdCodeLives": base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, language), | |||||
"ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, language), | |||||
"ResetPwdCodeLives": timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, language), | |||||
"Code": code, | "Code": code, | ||||
} | } | ||||
func SendActivateEmailMail(locale Locale, u *User, email *EmailAddress) { | func SendActivateEmailMail(locale Locale, u *User, email *EmailAddress) { | ||||
data := map[string]interface{}{ | data := map[string]interface{}{ | ||||
"DisplayName": u.DisplayName(), | "DisplayName": u.DisplayName(), | ||||
"ActiveCodeLives": base.MinutesToFriendly(setting.Service.ActiveCodeLives, locale.Language()), | |||||
"ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale.Language()), | |||||
"Code": u.GenerateEmailActivateCode(email.Email), | "Code": u.GenerateEmailActivateCode(email.Email), | ||||
"Email": email.Email, | "Email": email.Email, | ||||
} | } |
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
) | ) | ||||
RepoID int64 `xorm:"INDEX(s)"` | RepoID int64 `xorm:"INDEX(s)"` | ||||
Type int `xorm:"INDEX(s)"` | Type int `xorm:"INDEX(s)"` | ||||
Config map[string]interface{} `xorm:"JSON"` | Config map[string]interface{} `xorm:"JSON"` | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX CREATED"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` | |||||
} | } | ||||
sess := x.NewSession() | sess := x.NewSession() |
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
) | ) | ||||
func addIssueClosedTime(x *xorm.Engine) error { | func addIssueClosedTime(x *xorm.Engine) error { | ||||
// Issue see models/issue.go | // Issue see models/issue.go | ||||
type Issue struct { | type Issue struct { | ||||
ClosedUnix util.TimeStamp `xorm:"INDEX"` | |||||
ClosedUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
} | } | ||||
if err := x.Sync2(new(Issue)); err != nil { | if err := x.Sync2(new(Issue)); err != nil { |
package migrations | package migrations | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
) | ) | ||||
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not. | IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not. | ||||
NumComments int | NumComments int | ||||
DeadlineUnix util.TimeStamp `xorm:"INDEX"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
ClosedUnix util.TimeStamp `xorm:"INDEX"` | |||||
DeadlineUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
ClosedUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
} | } | ||||
// Updated the comment table | // Updated the comment table | ||||
Content string `xorm:"TEXT"` | Content string `xorm:"TEXT"` | ||||
RenderedContent string `xorm:"-"` | RenderedContent string `xorm:"-"` | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
// Reference issue in commit message | // Reference issue in commit message | ||||
CommitSHA string `xorm:"VARCHAR(40)"` | CommitSHA string `xorm:"VARCHAR(40)"` |
package migrations | package migrations | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
) | ) | ||||
UserID int64 `xorm:"INDEX"` | UserID int64 `xorm:"INDEX"` | ||||
Raw []byte | Raw []byte | ||||
Counter uint32 | Counter uint32 | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
return x.Sync2(&U2FRegistration{}) | return x.Sync2(&U2FRegistration{}) | ||||
} | } |
"crypto/sha256" | "crypto/sha256" | ||||
"fmt" | "fmt" | ||||
"code.gitea.io/gitea/modules/generate" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
"golang.org/x/crypto/pbkdf2" | "golang.org/x/crypto/pbkdf2" | ||||
"code.gitea.io/gitea/modules/generate" | |||||
"code.gitea.io/gitea/modules/util" | |||||
) | ) | ||||
func addScratchHash(x *xorm.Engine) error { | func addScratchHash(x *xorm.Engine) error { | ||||
ScratchToken string | ScratchToken string | ||||
ScratchSalt string | ScratchSalt string | ||||
ScratchHash string | ScratchHash string | ||||
LastUsedPasscode string `xorm:"VARCHAR(10)"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
LastUsedPasscode string `xorm:"VARCHAR(10)"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
if err := x.Sync2(new(TwoFactor)); err != nil { | if err := x.Sync2(new(TwoFactor)); err != nil { |
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
) | ) | ||||
ReviewerID int64 `xorm:"index"` | ReviewerID int64 `xorm:"index"` | ||||
IssueID int64 `xorm:"index"` | IssueID int64 `xorm:"index"` | ||||
Content string | Content string | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
if err := x.Sync2(new(Review)); err != nil { | if err := x.Sync2(new(Review)); err != nil { |
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
) | ) | ||||
RepoID int64 `xorm:"INDEX(s)"` | RepoID int64 `xorm:"INDEX(s)"` | ||||
Type int `xorm:"INDEX(s)"` | Type int `xorm:"INDEX(s)"` | ||||
Config map[string]interface{} `xorm:"JSON"` | Config map[string]interface{} `xorm:"JSON"` | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX CREATED"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` | |||||
} | } | ||||
sess := x.NewSession() | sess := x.NewSession() |
package migrations | package migrations | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
) | ) | ||||
UploaderID int64 `xorm:"INDEX DEFAULT 0"` | UploaderID int64 `xorm:"INDEX DEFAULT 0"` | ||||
CommentID int64 | CommentID int64 | ||||
Name string | Name string | ||||
DownloadCount int64 `xorm:"DEFAULT 0"` | |||||
Size int64 `xorm:"DEFAULT 0"` | |||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
DownloadCount int64 `xorm:"DEFAULT 0"` | |||||
Size int64 `xorm:"DEFAULT 0"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
} | } | ||||
return x.Sync2(new(Attachment)) | return x.Sync2(new(Attachment)) |
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"github.com/go-xorm/xorm" | |||||
"code.gitea.io/gitea/modules/generate" | "code.gitea.io/gitea/modules/generate" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | |||||
) | ) | ||||
func hashAppToken(x *xorm.Engine) error { | func hashAppToken(x *xorm.Engine) error { | ||||
TokenSalt string | TokenSalt string | ||||
TokenLastEight string `xorm:"token_last_eight"` | TokenLastEight string `xorm:"token_last_eight"` | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
HasRecentActivity bool `xorm:"-"` | |||||
HasUsed bool `xorm:"-"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
HasRecentActivity bool `xorm:"-"` | |||||
HasUsed bool `xorm:"-"` | |||||
} | } | ||||
// First remove the index | // First remove the index |
import ( | import ( | ||||
"fmt" | "fmt" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
type ( | type ( | ||||
Issue *Issue `xorm:"-"` | Issue *Issue `xorm:"-"` | ||||
Repository *Repository `xorm:"-"` | Repository *Repository `xorm:"-"` | ||||
CreatedUnix util.TimeStamp `xorm:"created INDEX NOT NULL"` | |||||
UpdatedUnix util.TimeStamp `xorm:"updated INDEX NOT NULL"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created INDEX NOT NULL"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated INDEX NOT NULL"` | |||||
} | } | ||||
// CreateOrUpdateIssueNotifications creates an issue notification | // CreateOrUpdateIssueNotifications creates an issue notification |
"net/url" | "net/url" | ||||
"time" | "time" | ||||
"github.com/go-xorm/xorm" | |||||
uuid "github.com/satori/go.uuid" | |||||
"code.gitea.io/gitea/modules/secret" | "code.gitea.io/gitea/modules/secret" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/dgrijalva/jwt-go" | "github.com/dgrijalva/jwt-go" | ||||
"github.com/go-xorm/xorm" | |||||
uuid "github.com/satori/go.uuid" | |||||
"golang.org/x/crypto/bcrypt" | "golang.org/x/crypto/bcrypt" | ||||
) | ) | ||||
RedirectURIs []string `xorm:"redirect_uris JSON TEXT"` | RedirectURIs []string `xorm:"redirect_uris JSON TEXT"` | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
// TableName sets the table name to `oauth2_application` | // TableName sets the table name to `oauth2_application` | ||||
CodeChallenge string | CodeChallenge string | ||||
CodeChallengeMethod string | CodeChallengeMethod string | ||||
RedirectURI string | RedirectURI string | ||||
ValidUntil util.TimeStamp `xorm:"index"` | |||||
ValidUntil timeutil.TimeStamp `xorm:"index"` | |||||
} | } | ||||
// TableName sets the table name to `oauth2_authorization_code` | // TableName sets the table name to `oauth2_authorization_code` | ||||
Application *OAuth2Application `xorm:"-"` | Application *OAuth2Application `xorm:"-"` | ||||
ApplicationID int64 `xorm:"INDEX unique(user_application)"` | ApplicationID int64 `xorm:"INDEX unique(user_application)"` | ||||
Counter int64 `xorm:"NOT NULL DEFAULT 1"` | Counter int64 `xorm:"NOT NULL DEFAULT 1"` | ||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||||
} | } | ||||
// TableName sets the table name to `oauth2_grant` | // TableName sets the table name to `oauth2_grant` |
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/sync" | "code.gitea.io/gitea/modules/sync" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
ProtectedBranch *ProtectedBranch `xorm:"-"` | ProtectedBranch *ProtectedBranch `xorm:"-"` | ||||
MergeBase string `xorm:"VARCHAR(40)"` | MergeBase string `xorm:"VARCHAR(40)"` | ||||
HasMerged bool `xorm:"INDEX"` | |||||
MergedCommitID string `xorm:"VARCHAR(40)"` | |||||
MergerID int64 `xorm:"INDEX"` | |||||
Merger *User `xorm:"-"` | |||||
MergedUnix util.TimeStamp `xorm:"updated INDEX"` | |||||
HasMerged bool `xorm:"INDEX"` | |||||
MergedCommitID string `xorm:"VARCHAR(40)"` | |||||
MergerID int64 `xorm:"INDEX"` | |||||
Merger *User `xorm:"-"` | |||||
MergedUnix timeutil.TimeStamp `xorm:"updated INDEX"` | |||||
} | } | ||||
// Note: don't try to get Issue because will end up recursive querying. | // Note: don't try to get Issue because will end up recursive querying. | ||||
} | } | ||||
if commit != nil { | if commit != nil { | ||||
pr.MergedCommitID = commit.ID.String() | pr.MergedCommitID = commit.ID.String() | ||||
pr.MergedUnix = util.TimeStamp(commit.Author.When.Unix()) | |||||
pr.MergedUnix = timeutil.TimeStamp(commit.Author.When.Unix()) | |||||
pr.Status = PullRequestStatusManuallyMerged | pr.Status = PullRequestStatusManuallyMerged | ||||
merger, _ := GetUserByEmail(commit.Author.Email) | merger, _ := GetUserByEmail(commit.Author.Email) | ||||
"code.gitea.io/gitea/modules/process" | "code.gitea.io/gitea/modules/process" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"xorm.io/builder" | "xorm.io/builder" | ||||
) | ) | ||||
Title string | Title string | ||||
Sha1 string `xorm:"VARCHAR(40)"` | Sha1 string `xorm:"VARCHAR(40)"` | ||||
NumCommits int64 | NumCommits int64 | ||||
NumCommitsBehind int64 `xorm:"-"` | |||||
Note string `xorm:"TEXT"` | |||||
IsDraft bool `xorm:"NOT NULL DEFAULT false"` | |||||
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"` | |||||
IsTag bool `xorm:"NOT NULL DEFAULT false"` | |||||
Attachments []*Attachment `xorm:"-"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX"` | |||||
NumCommitsBehind int64 `xorm:"-"` | |||||
Note string `xorm:"TEXT"` | |||||
IsDraft bool `xorm:"NOT NULL DEFAULT false"` | |||||
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"` | |||||
IsTag bool `xorm:"NOT NULL DEFAULT false"` | |||||
Attachments []*Attachment `xorm:"-"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
} | } | ||||
func (r *Release) loadAttributes(e Engine) error { | func (r *Release) loadAttributes(e Engine) error { | ||||
} | } | ||||
rel.Sha1 = commit.ID.String() | rel.Sha1 = commit.ID.String() | ||||
rel.CreatedUnix = util.TimeStamp(commit.Author.When.Unix()) | |||||
rel.CreatedUnix = timeutil.TimeStamp(commit.Author.When.Unix()) | |||||
rel.NumCommits, err = commit.CommitsCount() | rel.NumCommits, err = commit.CommitsCount() | ||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("CommitsCount: %v", err) | return fmt.Errorf("CommitsCount: %v", err) | ||||
} | } | ||||
} else { | } else { | ||||
rel.CreatedUnix = util.TimeStampNow() | |||||
rel.CreatedUnix = timeutil.TimeStampNow() | |||||
} | } | ||||
return nil | return nil | ||||
} | } |
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/sync" | "code.gitea.io/gitea/modules/sync" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
// Avatar: ID(10-20)-md5(32) - must fit into 64 symbols | // Avatar: ID(10-20)-md5(32) - must fit into 64 symbols | ||||
Avatar string `xorm:"VARCHAR(64)"` | Avatar string `xorm:"VARCHAR(64)"` | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
// ColorFormat returns a colored string to represent this repo | // ColorFormat returns a colored string to represent this repo | ||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
Interval: setting.Mirror.DefaultInterval, | Interval: setting.Mirror.DefaultInterval, | ||||
EnablePrune: true, | EnablePrune: true, | ||||
NextUpdateUnix: util.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval), | |||||
NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval), | |||||
}); err != nil { | }); err != nil { | ||||
return repo, fmt.Errorf("InsertOne: %v", err) | return repo, fmt.Errorf("InsertOne: %v", err) | ||||
} | } |
"code.gitea.io/gitea/modules/process" | "code.gitea.io/gitea/modules/process" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/sync" | "code.gitea.io/gitea/modules/sync" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
Interval time.Duration | Interval time.Duration | ||||
EnablePrune bool `xorm:"NOT NULL DEFAULT true"` | EnablePrune bool `xorm:"NOT NULL DEFAULT true"` | ||||
UpdatedUnix util.TimeStamp `xorm:"INDEX"` | |||||
NextUpdateUnix util.TimeStamp `xorm:"INDEX"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
NextUpdateUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
address string `xorm:"-"` | address string `xorm:"-"` | ||||
} | } | ||||
// BeforeInsert will be invoked by XORM before inserting a record | // BeforeInsert will be invoked by XORM before inserting a record | ||||
func (m *Mirror) BeforeInsert() { | func (m *Mirror) BeforeInsert() { | ||||
if m != nil { | if m != nil { | ||||
m.UpdatedUnix = util.TimeStampNow() | |||||
m.NextUpdateUnix = util.TimeStampNow() | |||||
m.UpdatedUnix = timeutil.TimeStampNow() | |||||
m.NextUpdateUnix = timeutil.TimeStampNow() | |||||
} | } | ||||
} | } | ||||
// ScheduleNextUpdate calculates and sets next update time. | // ScheduleNextUpdate calculates and sets next update time. | ||||
func (m *Mirror) ScheduleNextUpdate() { | func (m *Mirror) ScheduleNextUpdate() { | ||||
if m.Interval != 0 { | if m.Interval != 0 { | ||||
m.NextUpdateUnix = util.TimeStampNow().AddDuration(m.Interval) | |||||
m.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(m.Interval) | |||||
} else { | } else { | ||||
m.NextUpdateUnix = 0 | m.NextUpdateUnix = 0 | ||||
} | } | ||||
cache.Remove(m.Repo.GetCommitsCountCacheKey(branches[i].Name, true)) | cache.Remove(m.Repo.GetCommitsCountCacheKey(branches[i].Name, true)) | ||||
} | } | ||||
m.UpdatedUnix = util.TimeStampNow() | |||||
m.UpdatedUnix = timeutil.TimeStampNow() | |||||
return parseRemoteUpdateOutput(output), true | return parseRemoteUpdateOutput(output), true | ||||
} | } | ||||
import ( | import ( | ||||
"encoding/json" | "encoding/json" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
// RepoUnit describes all units of a repository | // RepoUnit describes all units of a repository | ||||
type RepoUnit struct { | type RepoUnit struct { | ||||
ID int64 | ID int64 | ||||
RepoID int64 `xorm:"INDEX(s)"` | |||||
Type UnitType `xorm:"INDEX(s)"` | |||||
Config core.Conversion `xorm:"TEXT"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX CREATED"` | |||||
RepoID int64 `xorm:"INDEX(s)"` | |||||
Type UnitType `xorm:"INDEX(s)"` | |||||
Config core.Conversion `xorm:"TEXT"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` | |||||
} | } | ||||
// UnitConfig describes common unit config | // UnitConfig describes common unit config |
"fmt" | "fmt" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
"xorm.io/builder" | "xorm.io/builder" | ||||
IssueID int64 `xorm:"index"` | IssueID int64 `xorm:"index"` | ||||
Content string | Content string | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
// CodeComments are the initial code comments of the review | // CodeComments are the initial code comments of the review | ||||
CodeComments CodeComments `xorm:"-"` | CodeComments CodeComments `xorm:"-"` | ||||
type PullReviewersWithType struct { | type PullReviewersWithType struct { | ||||
User `xorm:"extends"` | User `xorm:"extends"` | ||||
Type ReviewType | Type ReviewType | ||||
ReviewUpdatedUnix util.TimeStamp `xorm:"review_updated_unix"` | |||||
ReviewUpdatedUnix timeutil.TimeStamp `xorm:"review_updated_unix"` | |||||
} | } | ||||
// GetReviewersByPullID gets all reviewers for a pull request with the statuses | // GetReviewersByPullID gets all reviewers for a pull request with the statuses |
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/process" | "code.gitea.io/gitea/modules/process" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
Type KeyType `xorm:"NOT NULL DEFAULT 1"` | Type KeyType `xorm:"NOT NULL DEFAULT 1"` | ||||
LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"` | LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"` | ||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"updated"` | |||||
HasRecentActivity bool `xorm:"-"` | |||||
HasUsed bool `xorm:"-"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||||
HasRecentActivity bool `xorm:"-"` | |||||
HasUsed bool `xorm:"-"` | |||||
} | } | ||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object. | // AfterLoad is invoked from XORM after setting the values of all fields of this object. | ||||
func (key *PublicKey) AfterLoad() { | func (key *PublicKey) AfterLoad() { | ||||
key.HasUsed = key.UpdatedUnix > key.CreatedUnix | key.HasUsed = key.UpdatedUnix > key.CreatedUnix | ||||
key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > util.TimeStampNow() | |||||
key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow() | |||||
} | } | ||||
// OmitEmail returns content of public key without email address. | // OmitEmail returns content of public key without email address. | ||||
} | } | ||||
_, err := x.ID(id).Cols("updated_unix").Update(&PublicKey{ | _, err := x.ID(id).Cols("updated_unix").Update(&PublicKey{ | ||||
UpdatedUnix: util.TimeStampNow(), | |||||
UpdatedUnix: timeutil.TimeStampNow(), | |||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
return err | return err | ||||
Mode AccessMode `xorm:"NOT NULL DEFAULT 1"` | Mode AccessMode `xorm:"NOT NULL DEFAULT 1"` | ||||
CreatedUnix util.TimeStamp `xorm:"created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"updated"` | |||||
HasRecentActivity bool `xorm:"-"` | |||||
HasUsed bool `xorm:"-"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||||
HasRecentActivity bool `xorm:"-"` | |||||
HasUsed bool `xorm:"-"` | |||||
} | } | ||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object. | // AfterLoad is invoked from XORM after setting the values of all fields of this object. | ||||
func (key *DeployKey) AfterLoad() { | func (key *DeployKey) AfterLoad() { | ||||
key.HasUsed = key.UpdatedUnix > key.CreatedUnix | key.HasUsed = key.UpdatedUnix > key.CreatedUnix | ||||
key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > util.TimeStampNow() | |||||
key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow() | |||||
} | } | ||||
// GetContent gets associated public key content. | // GetContent gets associated public key content. |
"crypto/subtle" | "crypto/subtle" | ||||
"time" | "time" | ||||
gouuid "github.com/satori/go.uuid" | |||||
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/generate" | "code.gitea.io/gitea/modules/generate" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
gouuid "github.com/satori/go.uuid" | |||||
) | ) | ||||
// AccessToken represents a personal access token. | // AccessToken represents a personal access token. | ||||
TokenSalt string | TokenSalt string | ||||
TokenLastEight string `xorm:"token_last_eight"` | TokenLastEight string `xorm:"token_last_eight"` | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
HasRecentActivity bool `xorm:"-"` | |||||
HasUsed bool `xorm:"-"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
HasRecentActivity bool `xorm:"-"` | |||||
HasUsed bool `xorm:"-"` | |||||
} | } | ||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object. | // AfterLoad is invoked from XORM after setting the values of all fields of this object. | ||||
func (t *AccessToken) AfterLoad() { | func (t *AccessToken) AfterLoad() { | ||||
t.HasUsed = t.UpdatedUnix > t.CreatedUnix | t.HasUsed = t.UpdatedUnix > t.CreatedUnix | ||||
t.HasRecentActivity = t.UpdatedUnix.AddDuration(7*24*time.Hour) > util.TimeStampNow() | |||||
t.HasRecentActivity = t.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow() | |||||
} | } | ||||
// NewAccessToken creates new access token. | // NewAccessToken creates new access token. |
"regexp" | "regexp" | ||||
"strings" | "strings" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"xorm.io/builder" | "xorm.io/builder" | ||||
) | ) | ||||
ID int64 | ID int64 | ||||
Name string `xorm:"UNIQUE VARCHAR(25)"` | Name string `xorm:"UNIQUE VARCHAR(25)"` | ||||
RepoCount int | RepoCount int | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
// RepoTopic represents associated repositories and topics | // RepoTopic represents associated repositories and topics |
"fmt" | "fmt" | ||||
"io" | "io" | ||||
"github.com/pquerna/otp/totp" | |||||
"golang.org/x/crypto/pbkdf2" | |||||
"code.gitea.io/gitea/modules/generate" | "code.gitea.io/gitea/modules/generate" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/pquerna/otp/totp" | |||||
"golang.org/x/crypto/pbkdf2" | |||||
) | ) | ||||
// TwoFactor represents a two-factor authentication token. | // TwoFactor represents a two-factor authentication token. | ||||
Secret string | Secret string | ||||
ScratchSalt string | ScratchSalt string | ||||
ScratchHash string | ScratchHash string | ||||
LastUsedPasscode string `xorm:"VARCHAR(10)"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
LastUsedPasscode string `xorm:"VARCHAR(10)"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
// GenerateScratchToken recreates the scratch token the user is using. | // GenerateScratchToken recreates the scratch token the user is using. |
import ( | import ( | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/tstranex/u2f" | "github.com/tstranex/u2f" | ||||
) | ) | ||||
Name string | Name string | ||||
UserID int64 `xorm:"INDEX"` | UserID int64 `xorm:"INDEX"` | ||||
Raw []byte | Raw []byte | ||||
Counter uint32 `xorm:"BIGINT"` | |||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
Counter uint32 `xorm:"BIGINT"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
// TableName returns a better table name for U2FRegistration | // TableName returns a better table name for U2FRegistration |
"time" | "time" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// env keys for git hooks need | // env keys for git hooks need | ||||
IsDraft: false, | IsDraft: false, | ||||
IsPrerelease: false, | IsPrerelease: false, | ||||
IsTag: true, | IsTag: true, | ||||
CreatedUnix: util.TimeStamp(createdAt.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(createdAt.Unix()), | |||||
} | } | ||||
if author != nil { | if author != nil { | ||||
rel.PublisherID = author.ID | rel.PublisherID = author.ID | ||||
} | } | ||||
} else { | } else { | ||||
rel.Sha1 = commit.ID.String() | rel.Sha1 = commit.ID.String() | ||||
rel.CreatedUnix = util.TimeStamp(createdAt.Unix()) | |||||
rel.CreatedUnix = timeutil.TimeStamp(createdAt.Unix()) | |||||
rel.NumCommits = commitsCount | rel.NumCommits = commitsCount | ||||
rel.IsDraft = false | rel.IsDraft = false | ||||
if rel.IsTag && author != nil { | if rel.IsTag && author != nil { |
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/structs" | "code.gitea.io/gitea/modules/structs" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
Language string `xorm:"VARCHAR(5)"` | Language string `xorm:"VARCHAR(5)"` | ||||
Description string | Description string | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
LastLoginUnix util.TimeStamp `xorm:"INDEX"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
LastLoginUnix timeutil.TimeStamp `xorm:"INDEX"` | |||||
// Remember visibility choice for convenience, true for private | // Remember visibility choice for convenience, true for private | ||||
LastRepoVisibility bool | LastRepoVisibility bool | ||||
// SetLastLogin set time to last login | // SetLastLogin set time to last login | ||||
func (u *User) SetLastLogin() { | func (u *User) SetLastLogin() { | ||||
u.LastLoginUnix = util.TimeStampNow() | |||||
u.LastLoginUnix = timeutil.TimeStampNow() | |||||
} | } | ||||
// UpdateDiffViewStyle updates the users diff view style | // UpdateDiffViewStyle updates the users diff view style |
import ( | import ( | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// UserHeatmapData represents the data needed to create a heatmap | // UserHeatmapData represents the data needed to create a heatmap | ||||
type UserHeatmapData struct { | type UserHeatmapData struct { | ||||
Timestamp util.TimeStamp `json:"timestamp"` | |||||
Contributions int64 `json:"contributions"` | |||||
Timestamp timeutil.TimeStamp `json:"timestamp"` | |||||
Contributions int64 `json:"contributions"` | |||||
} | } | ||||
// GetUserHeatmapDataByUser returns an array of UserHeatmapData | // GetUserHeatmapDataByUser returns an array of UserHeatmapData | ||||
sess := x.Select(groupBy+" AS timestamp, count(user_id) as contributions"). | sess := x.Select(groupBy+" AS timestamp, count(user_id) as contributions"). | ||||
Table("action"). | Table("action"). | ||||
Where("user_id = ?", user.ID). | Where("user_id = ?", user.ID). | ||||
And("created_unix > ?", (util.TimeStampNow() - 31536000)) | |||||
And("created_unix > ?", (timeutil.TimeStampNow() - 31536000)) | |||||
// * Heatmaps for individual users only include actions that the user themself | // * Heatmaps for individual users only include actions that the user themself | ||||
// did. | // did. |
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/sync" | "code.gitea.io/gitea/modules/sync" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
gouuid "github.com/satori/go.uuid" | gouuid "github.com/satori/go.uuid" | ||||
) | ) | ||||
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 | ||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
} | } | ||||
// AfterLoad updates the webhook object upon setting a column | // AfterLoad updates the webhook object upon setting a column |
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/validation" | "code.gitea.io/gitea/modules/validation" | ||||
) | ) | ||||
} | } | ||||
return 0 | return 0 | ||||
} | } | ||||
t.UpdatedUnix = util.TimeStampNow() | |||||
t.UpdatedUnix = timeutil.TimeStampNow() | |||||
if err = models.UpdateAccessToken(t); err != nil { | if err = models.UpdateAccessToken(t); err != nil { | ||||
log.Error("UpdateAccessToken: %v", err) | log.Error("UpdateAccessToken: %v", err) | ||||
} | } | ||||
return nil, false | return nil, false | ||||
} | } | ||||
} | } | ||||
token.UpdatedUnix = util.TimeStampNow() | |||||
token.UpdatedUnix = timeutil.TimeStampNow() | |||||
if err = models.UpdateAccessToken(token); err != nil { | if err = models.UpdateAccessToken(token); err != nil { | ||||
log.Error("UpdateAccessToken: %v", err) | log.Error("UpdateAccessToken: %v", err) | ||||
} | } |
"encoding/base64" | "encoding/base64" | ||||
"encoding/hex" | "encoding/hex" | ||||
"fmt" | "fmt" | ||||
"html/template" | |||||
"io" | "io" | ||||
"math" | "math" | ||||
"net/http" | "net/http" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/Unknwon/i18n" | |||||
) | ) | ||||
// EncodeMD5 encodes string to md5 hex value. | // EncodeMD5 encodes string to md5 hex value. | ||||
return SizedAvatarLink(email, DefaultAvatarSize) | return SizedAvatarLink(email, DefaultAvatarSize) | ||||
} | } | ||||
// Seconds-based time units | |||||
const ( | |||||
Minute = 60 | |||||
Hour = 60 * Minute | |||||
Day = 24 * Hour | |||||
Week = 7 * Day | |||||
Month = 30 * Day | |||||
Year = 12 * Month | |||||
) | |||||
func computeTimeDiff(diff int64, lang string) (int64, string) { | |||||
diffStr := "" | |||||
switch { | |||||
case diff <= 0: | |||||
diff = 0 | |||||
diffStr = i18n.Tr(lang, "tool.now") | |||||
case diff < 2: | |||||
diff = 0 | |||||
diffStr = i18n.Tr(lang, "tool.1s") | |||||
case diff < 1*Minute: | |||||
diffStr = i18n.Tr(lang, "tool.seconds", diff) | |||||
diff = 0 | |||||
case diff < 2*Minute: | |||||
diff -= 1 * Minute | |||||
diffStr = i18n.Tr(lang, "tool.1m") | |||||
case diff < 1*Hour: | |||||
diffStr = i18n.Tr(lang, "tool.minutes", diff/Minute) | |||||
diff -= diff / Minute * Minute | |||||
case diff < 2*Hour: | |||||
diff -= 1 * Hour | |||||
diffStr = i18n.Tr(lang, "tool.1h") | |||||
case diff < 1*Day: | |||||
diffStr = i18n.Tr(lang, "tool.hours", diff/Hour) | |||||
diff -= diff / Hour * Hour | |||||
case diff < 2*Day: | |||||
diff -= 1 * Day | |||||
diffStr = i18n.Tr(lang, "tool.1d") | |||||
case diff < 1*Week: | |||||
diffStr = i18n.Tr(lang, "tool.days", diff/Day) | |||||
diff -= diff / Day * Day | |||||
case diff < 2*Week: | |||||
diff -= 1 * Week | |||||
diffStr = i18n.Tr(lang, "tool.1w") | |||||
case diff < 1*Month: | |||||
diffStr = i18n.Tr(lang, "tool.weeks", diff/Week) | |||||
diff -= diff / Week * Week | |||||
case diff < 2*Month: | |||||
diff -= 1 * Month | |||||
diffStr = i18n.Tr(lang, "tool.1mon") | |||||
case diff < 1*Year: | |||||
diffStr = i18n.Tr(lang, "tool.months", diff/Month) | |||||
diff -= diff / Month * Month | |||||
case diff < 2*Year: | |||||
diff -= 1 * Year | |||||
diffStr = i18n.Tr(lang, "tool.1y") | |||||
default: | |||||
diffStr = i18n.Tr(lang, "tool.years", diff/Year) | |||||
diff -= (diff / Year) * Year | |||||
} | |||||
return diff, diffStr | |||||
} | |||||
// MinutesToFriendly returns a user friendly string with number of minutes | |||||
// converted to hours and minutes. | |||||
func MinutesToFriendly(minutes int, lang string) string { | |||||
duration := time.Duration(minutes) * time.Minute | |||||
return TimeSincePro(time.Now().Add(-duration), lang) | |||||
} | |||||
// TimeSincePro calculates the time interval and generate full user-friendly string. | |||||
func TimeSincePro(then time.Time, lang string) string { | |||||
return timeSincePro(then, time.Now(), lang) | |||||
} | |||||
func timeSincePro(then, now time.Time, lang string) string { | |||||
diff := now.Unix() - then.Unix() | |||||
if then.After(now) { | |||||
return i18n.Tr(lang, "tool.future") | |||||
} | |||||
if diff == 0 { | |||||
return i18n.Tr(lang, "tool.now") | |||||
} | |||||
var timeStr, diffStr string | |||||
for { | |||||
if diff == 0 { | |||||
break | |||||
} | |||||
diff, diffStr = computeTimeDiff(diff, lang) | |||||
timeStr += ", " + diffStr | |||||
} | |||||
return strings.TrimPrefix(timeStr, ", ") | |||||
} | |||||
func timeSince(then, now time.Time, lang string) string { | |||||
return timeSinceUnix(then.Unix(), now.Unix(), lang) | |||||
} | |||||
func timeSinceUnix(then, now int64, lang string) string { | |||||
lbl := "tool.ago" | |||||
diff := now - then | |||||
if then > now { | |||||
lbl = "tool.from_now" | |||||
diff = then - now | |||||
} | |||||
if diff <= 0 { | |||||
return i18n.Tr(lang, "tool.now") | |||||
} | |||||
_, diffStr := computeTimeDiff(diff, lang) | |||||
return i18n.Tr(lang, lbl, diffStr) | |||||
} | |||||
// RawTimeSince retrieves i18n key of time since t | |||||
func RawTimeSince(t time.Time, lang string) string { | |||||
return timeSince(t, time.Now(), lang) | |||||
} | |||||
// TimeSince calculates the time interval and generate user-friendly string. | |||||
func TimeSince(then time.Time, lang string) template.HTML { | |||||
return htmlTimeSince(then, time.Now(), lang) | |||||
} | |||||
func htmlTimeSince(then, now time.Time, lang string) template.HTML { | |||||
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`, | |||||
then.Format(setting.TimeFormat), | |||||
timeSince(then, now, lang))) | |||||
} | |||||
// TimeSinceUnix calculates the time interval and generate user-friendly string. | |||||
func TimeSinceUnix(then util.TimeStamp, lang string) template.HTML { | |||||
return htmlTimeSinceUnix(then, util.TimeStamp(time.Now().Unix()), lang) | |||||
} | |||||
func htmlTimeSinceUnix(then, now util.TimeStamp, lang string) template.HTML { | |||||
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`, | |||||
then.Format(setting.TimeFormat), | |||||
timeSinceUnix(int64(then), int64(now), lang))) | |||||
} | |||||
// Storage space size types | // Storage space size types | ||||
const ( | const ( | ||||
Byte = 1 | Byte = 1 |
import ( | import ( | ||||
"net/url" | "net/url" | ||||
"os" | |||||
"testing" | "testing" | ||||
"time" | |||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"github.com/Unknwon/i18n" | |||||
macaroni18n "github.com/go-macaron/i18n" | |||||
"github.com/stretchr/testify/assert" | "github.com/stretchr/testify/assert" | ||||
) | ) | ||||
var BaseDate time.Time | |||||
// time durations | |||||
const ( | |||||
DayDur = 24 * time.Hour | |||||
WeekDur = 7 * DayDur | |||||
MonthDur = 30 * DayDur | |||||
YearDur = 12 * MonthDur | |||||
) | |||||
func TestMain(m *testing.M) { | |||||
// setup | |||||
macaroni18n.I18n(macaroni18n.Options{ | |||||
Directory: "../../options/locale/", | |||||
DefaultLang: "en-US", | |||||
Langs: []string{"en-US"}, | |||||
Names: []string{"english"}, | |||||
}) | |||||
BaseDate = time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) | |||||
// run the tests | |||||
retVal := m.Run() | |||||
os.Exit(retVal) | |||||
} | |||||
func TestEncodeMD5(t *testing.T) { | func TestEncodeMD5(t *testing.T) { | ||||
assert.Equal(t, | assert.Equal(t, | ||||
"3858f62230ac3c915f300c664312c63f", | "3858f62230ac3c915f300c664312c63f", | ||||
) | ) | ||||
} | } | ||||
func TestComputeTimeDiff(t *testing.T) { | |||||
// test that for each offset in offsets, | |||||
// computeTimeDiff(base + offset) == (offset, str) | |||||
test := func(base int64, str string, offsets ...int64) { | |||||
for _, offset := range offsets { | |||||
diff, diffStr := computeTimeDiff(base+offset, "en") | |||||
assert.Equal(t, offset, diff) | |||||
assert.Equal(t, str, diffStr) | |||||
} | |||||
} | |||||
test(0, "now", 0) | |||||
test(1, "1 second", 0) | |||||
test(2, "2 seconds", 0) | |||||
test(Minute, "1 minute", 0, 1, 30, Minute-1) | |||||
test(2*Minute, "2 minutes", 0, Minute-1) | |||||
test(Hour, "1 hour", 0, 1, Hour-1) | |||||
test(5*Hour, "5 hours", 0, Hour-1) | |||||
test(Day, "1 day", 0, 1, Day-1) | |||||
test(5*Day, "5 days", 0, Day-1) | |||||
test(Week, "1 week", 0, 1, Week-1) | |||||
test(3*Week, "3 weeks", 0, 4*Day+25000) | |||||
test(Month, "1 month", 0, 1, Month-1) | |||||
test(10*Month, "10 months", 0, Month-1) | |||||
test(Year, "1 year", 0, Year-1) | |||||
test(3*Year, "3 years", 0, Year-1) | |||||
} | |||||
func TestMinutesToFriendly(t *testing.T) { | |||||
// test that a number of minutes yields the expected string | |||||
test := func(expected string, minutes int) { | |||||
actual := MinutesToFriendly(minutes, "en") | |||||
assert.Equal(t, expected, actual) | |||||
} | |||||
test("1 minute", 1) | |||||
test("2 minutes", 2) | |||||
test("1 hour", 60) | |||||
test("1 hour, 1 minute", 61) | |||||
test("1 hour, 2 minutes", 62) | |||||
test("2 hours", 120) | |||||
} | |||||
func TestTimeSince(t *testing.T) { | |||||
assert.Equal(t, "now", timeSince(BaseDate, BaseDate, "en")) | |||||
// test that each diff in `diffs` yields the expected string | |||||
test := func(expected string, diffs ...time.Duration) { | |||||
for _, diff := range diffs { | |||||
actual := timeSince(BaseDate, BaseDate.Add(diff), "en") | |||||
assert.Equal(t, i18n.Tr("en", "tool.ago", expected), actual) | |||||
actual = timeSince(BaseDate.Add(diff), BaseDate, "en") | |||||
assert.Equal(t, i18n.Tr("en", "tool.from_now", expected), actual) | |||||
} | |||||
} | |||||
test("1 second", time.Second, time.Second+50*time.Millisecond) | |||||
test("2 seconds", 2*time.Second, 2*time.Second+50*time.Millisecond) | |||||
test("1 minute", time.Minute, time.Minute+30*time.Second) | |||||
test("2 minutes", 2*time.Minute, 2*time.Minute+30*time.Second) | |||||
test("1 hour", time.Hour, time.Hour+30*time.Minute) | |||||
test("2 hours", 2*time.Hour, 2*time.Hour+30*time.Minute) | |||||
test("1 day", DayDur, DayDur+12*time.Hour) | |||||
test("2 days", 2*DayDur, 2*DayDur+12*time.Hour) | |||||
test("1 week", WeekDur, WeekDur+3*DayDur) | |||||
test("2 weeks", 2*WeekDur, 2*WeekDur+3*DayDur) | |||||
test("1 month", MonthDur, MonthDur+15*DayDur) | |||||
test("2 months", 2*MonthDur, 2*MonthDur+15*DayDur) | |||||
test("1 year", YearDur, YearDur+6*MonthDur) | |||||
test("2 years", 2*YearDur, 2*YearDur+6*MonthDur) | |||||
} | |||||
func TestTimeSincePro(t *testing.T) { | |||||
assert.Equal(t, "now", timeSincePro(BaseDate, BaseDate, "en")) | |||||
// test that a difference of `diff` yields the expected string | |||||
test := func(expected string, diff time.Duration) { | |||||
actual := timeSincePro(BaseDate, BaseDate.Add(diff), "en") | |||||
assert.Equal(t, expected, actual) | |||||
assert.Equal(t, "future", timeSincePro(BaseDate.Add(diff), BaseDate, "en")) | |||||
} | |||||
test("1 second", time.Second) | |||||
test("2 seconds", 2*time.Second) | |||||
test("1 minute", time.Minute) | |||||
test("1 minute, 1 second", time.Minute+time.Second) | |||||
test("1 minute, 59 seconds", time.Minute+59*time.Second) | |||||
test("2 minutes", 2*time.Minute) | |||||
test("1 hour", time.Hour) | |||||
test("1 hour, 1 second", time.Hour+time.Second) | |||||
test("1 hour, 59 minutes, 59 seconds", time.Hour+59*time.Minute+59*time.Second) | |||||
test("2 hours", 2*time.Hour) | |||||
test("1 day", DayDur) | |||||
test("1 day, 23 hours, 59 minutes, 59 seconds", | |||||
DayDur+23*time.Hour+59*time.Minute+59*time.Second) | |||||
test("2 days", 2*DayDur) | |||||
test("1 week", WeekDur) | |||||
test("2 weeks", 2*WeekDur) | |||||
test("1 month", MonthDur) | |||||
test("3 months", 3*MonthDur) | |||||
test("1 year", YearDur) | |||||
test("2 years, 3 months, 1 week, 2 days, 4 hours, 12 minutes, 17 seconds", | |||||
2*YearDur+3*MonthDur+WeekDur+2*DayDur+4*time.Hour+ | |||||
12*time.Minute+17*time.Second) | |||||
} | |||||
func TestHtmlTimeSince(t *testing.T) { | |||||
setting.TimeFormat = time.UnixDate | |||||
// test that `diff` yields a result containing `expected` | |||||
test := func(expected string, diff time.Duration) { | |||||
actual := htmlTimeSince(BaseDate, BaseDate.Add(diff), "en") | |||||
assert.Contains(t, actual, `title="Sat Jan 1 00:00:00 UTC 2000"`) | |||||
assert.Contains(t, actual, expected) | |||||
} | |||||
test("1 second", time.Second) | |||||
test("3 minutes", 3*time.Minute+5*time.Second) | |||||
test("1 day", DayDur+18*time.Hour) | |||||
test("1 week", WeekDur+6*DayDur) | |||||
test("3 months", 3*MonthDur+3*WeekDur) | |||||
test("2 years", 2*YearDur) | |||||
test("3 years", 3*YearDur+11*MonthDur+4*WeekDur) | |||||
} | |||||
func TestFileSize(t *testing.T) { | func TestFileSize(t *testing.T) { | ||||
var size int64 = 512 | var size int64 = 512 | ||||
assert.Equal(t, "512B", FileSize(size)) | assert.Equal(t, "512B", FileSize(size)) |
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/migrations/base" | "code.gitea.io/gitea/modules/migrations/base" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
gouuid "github.com/satori/go.uuid" | gouuid "github.com/satori/go.uuid" | ||||
) | ) | ||||
func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) error { | func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) error { | ||||
var mss = make([]*models.Milestone, 0, len(milestones)) | var mss = make([]*models.Milestone, 0, len(milestones)) | ||||
for _, milestone := range milestones { | for _, milestone := range milestones { | ||||
var deadline util.TimeStamp | |||||
var deadline timeutil.TimeStamp | |||||
if milestone.Deadline != nil { | if milestone.Deadline != nil { | ||||
deadline = util.TimeStamp(milestone.Deadline.Unix()) | |||||
deadline = timeutil.TimeStamp(milestone.Deadline.Unix()) | |||||
} | } | ||||
if deadline == 0 { | if deadline == 0 { | ||||
deadline = util.TimeStamp(time.Date(9999, 1, 1, 0, 0, 0, 0, setting.UILocation).Unix()) | |||||
deadline = timeutil.TimeStamp(time.Date(9999, 1, 1, 0, 0, 0, 0, setting.DefaultUILocation).Unix()) | |||||
} | } | ||||
var ms = models.Milestone{ | var ms = models.Milestone{ | ||||
RepoID: g.repo.ID, | RepoID: g.repo.ID, | ||||
DeadlineUnix: deadline, | DeadlineUnix: deadline, | ||||
} | } | ||||
if ms.IsClosed && milestone.Closed != nil { | if ms.IsClosed && milestone.Closed != nil { | ||||
ms.ClosedDateUnix = util.TimeStamp(milestone.Closed.Unix()) | |||||
ms.ClosedDateUnix = timeutil.TimeStamp(milestone.Closed.Unix()) | |||||
} | } | ||||
mss = append(mss, &ms) | mss = append(mss, &ms) | ||||
} | } | ||||
IsDraft: release.Draft, | IsDraft: release.Draft, | ||||
IsPrerelease: release.Prerelease, | IsPrerelease: release.Prerelease, | ||||
IsTag: false, | IsTag: false, | ||||
CreatedUnix: util.TimeStamp(release.Created.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(release.Created.Unix()), | |||||
} | } | ||||
// calc NumCommits | // calc NumCommits | ||||
Name: asset.Name, | Name: asset.Name, | ||||
DownloadCount: int64(*asset.DownloadCount), | DownloadCount: int64(*asset.DownloadCount), | ||||
Size: int64(*asset.Size), | Size: int64(*asset.Size), | ||||
CreatedUnix: util.TimeStamp(asset.Created.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(asset.Created.Unix()), | |||||
} | } | ||||
// download attachment | // download attachment | ||||
IsLocked: issue.IsLocked, | IsLocked: issue.IsLocked, | ||||
MilestoneID: milestoneID, | MilestoneID: milestoneID, | ||||
Labels: labels, | Labels: labels, | ||||
CreatedUnix: util.TimeStamp(issue.Created.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(issue.Created.Unix()), | |||||
} | } | ||||
if issue.Closed != nil { | if issue.Closed != nil { | ||||
is.ClosedUnix = util.TimeStamp(issue.Closed.Unix()) | |||||
is.ClosedUnix = timeutil.TimeStamp(issue.Closed.Unix()) | |||||
} | } | ||||
// TODO: add reactions | // TODO: add reactions | ||||
iss = append(iss, &is) | iss = append(iss, &is) | ||||
OriginalAuthor: comment.PosterName, | OriginalAuthor: comment.PosterName, | ||||
OriginalAuthorID: comment.PosterID, | OriginalAuthorID: comment.PosterID, | ||||
Content: comment.Content, | Content: comment.Content, | ||||
CreatedUnix: util.TimeStamp(comment.Created.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(comment.Created.Unix()), | |||||
}) | }) | ||||
// TODO: Reactions | // TODO: Reactions | ||||
IsClosed: pr.State == "closed", | IsClosed: pr.State == "closed", | ||||
IsLocked: pr.IsLocked, | IsLocked: pr.IsLocked, | ||||
Labels: labels, | Labels: labels, | ||||
CreatedUnix: util.TimeStamp(pr.Created.Unix()), | |||||
CreatedUnix: timeutil.TimeStamp(pr.Created.Unix()), | |||||
}, | }, | ||||
} | } | ||||
if pullRequest.Issue.IsClosed && pr.Closed != nil { | if pullRequest.Issue.IsClosed && pr.Closed != nil { | ||||
pullRequest.Issue.ClosedUnix = util.TimeStamp(pr.Closed.Unix()) | |||||
pullRequest.Issue.ClosedUnix = timeutil.TimeStamp(pr.Closed.Unix()) | |||||
} | } | ||||
if pullRequest.HasMerged && pr.MergedTime != nil { | if pullRequest.HasMerged && pr.MergedTime != nil { | ||||
pullRequest.MergedUnix = util.TimeStamp(pr.MergedTime.Unix()) | |||||
pullRequest.MergedUnix = timeutil.TimeStamp(pr.MergedTime.Unix()) | |||||
pullRequest.MergedCommitID = pr.MergeCommitSHA | pullRequest.MergedCommitID = pr.MergeCommitSHA | ||||
pullRequest.MergerID = g.doer.ID | pullRequest.MergerID = g.doer.ID | ||||
} | } |
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// Merge merges pull request to base repository. | // Merge merges pull request to base repository. | ||||
return fmt.Errorf("GetBranchCommit: %v", err) | return fmt.Errorf("GetBranchCommit: %v", err) | ||||
} | } | ||||
pr.MergedUnix = util.TimeStampNow() | |||||
pr.MergedUnix = timeutil.TimeStampNow() | |||||
pr.Merger = doer | pr.Merger = doer | ||||
pr.MergerID = doer.ID | pr.MergerID = doer.ID | ||||
// Time settings | // Time settings | ||||
TimeFormat string | TimeFormat string | ||||
// UILocation is the location on the UI, so that we can display the time on UI. | |||||
DefaultUILocation = time.Local | |||||
CSRFCookieName = "_csrf" | CSRFCookieName = "_csrf" | ||||
CSRFCookieHTTPOnly = true | CSRFCookieHTTPOnly = true | ||||
HasRobotsTxt bool | HasRobotsTxt bool | ||||
InternalToken string // internal access token | InternalToken string // internal access token | ||||
IterateBufferSize int | IterateBufferSize int | ||||
// UILocation is the location on the UI, so that we can display the time on UI. | |||||
// Currently only show the default time.Local, it could be added to app.ini after UI is ready | |||||
UILocation = time.Local | |||||
) | ) | ||||
// DateLang transforms standard language locale name to corresponding value in datetime plugin. | // DateLang transforms standard language locale name to corresponding value in datetime plugin. | ||||
AttachmentMaxFiles = sec.Key("MAX_FILES").MustInt(5) | AttachmentMaxFiles = sec.Key("MAX_FILES").MustInt(5) | ||||
AttachmentEnabled = sec.Key("ENABLED").MustBool(true) | AttachmentEnabled = sec.Key("ENABLED").MustBool(true) | ||||
TimeFormatKey := Cfg.Section("time").Key("FORMAT").MustString("RFC1123") | |||||
TimeFormat = map[string]string{ | |||||
"ANSIC": time.ANSIC, | |||||
"UnixDate": time.UnixDate, | |||||
"RubyDate": time.RubyDate, | |||||
"RFC822": time.RFC822, | |||||
"RFC822Z": time.RFC822Z, | |||||
"RFC850": time.RFC850, | |||||
"RFC1123": time.RFC1123, | |||||
"RFC1123Z": time.RFC1123Z, | |||||
"RFC3339": time.RFC3339, | |||||
"RFC3339Nano": time.RFC3339Nano, | |||||
"Kitchen": time.Kitchen, | |||||
"Stamp": time.Stamp, | |||||
"StampMilli": time.StampMilli, | |||||
"StampMicro": time.StampMicro, | |||||
"StampNano": time.StampNano, | |||||
}[TimeFormatKey] | |||||
// When the TimeFormatKey does not exist in the previous map e.g.'2006-01-02 15:04:05' | |||||
if len(TimeFormat) == 0 { | |||||
TimeFormat = TimeFormatKey | |||||
TestTimeFormat, _ := time.Parse(TimeFormat, TimeFormat) | |||||
if TestTimeFormat.Format(time.RFC3339) != "2006-01-02T15:04:05Z" { | |||||
log.Fatal("Can't create time properly, please check your time format has 2006, 01, 02, 15, 04 and 05") | |||||
timeFormatKey := Cfg.Section("time").Key("FORMAT").MustString("") | |||||
if timeFormatKey != "" { | |||||
TimeFormat = map[string]string{ | |||||
"ANSIC": time.ANSIC, | |||||
"UnixDate": time.UnixDate, | |||||
"RubyDate": time.RubyDate, | |||||
"RFC822": time.RFC822, | |||||
"RFC822Z": time.RFC822Z, | |||||
"RFC850": time.RFC850, | |||||
"RFC1123": time.RFC1123, | |||||
"RFC1123Z": time.RFC1123Z, | |||||
"RFC3339": time.RFC3339, | |||||
"RFC3339Nano": time.RFC3339Nano, | |||||
"Kitchen": time.Kitchen, | |||||
"Stamp": time.Stamp, | |||||
"StampMilli": time.StampMilli, | |||||
"StampMicro": time.StampMicro, | |||||
"StampNano": time.StampNano, | |||||
}[timeFormatKey] | |||||
// When the TimeFormatKey does not exist in the previous map e.g.'2006-01-02 15:04:05' | |||||
if len(TimeFormat) == 0 { | |||||
TimeFormat = timeFormatKey | |||||
TestTimeFormat, _ := time.Parse(TimeFormat, TimeFormat) | |||||
if TestTimeFormat.Format(time.RFC3339) != "2006-01-02T15:04:05Z" { | |||||
log.Fatal("Can't create time properly, please check your time format has 2006, 01, 02, 15, 04 and 05") | |||||
} | |||||
log.Trace("Custom TimeFormat: %s", TimeFormat) | |||||
} | |||||
} | |||||
zone := Cfg.Section("time").Key("DEFAULT_UI_LOCATION").String() | |||||
if zone != "" { | |||||
DefaultUILocation, err = time.LoadLocation(zone) | |||||
if err != nil { | |||||
log.Fatal("Load time zone failed: %v", err) | |||||
} else { | |||||
log.Info("Default UI Location is %v", zone) | |||||
} | } | ||||
log.Trace("Custom TimeFormat: %s", TimeFormat) | |||||
} | |||||
if DefaultUILocation == nil { | |||||
DefaultUILocation = time.Local | |||||
} | } | ||||
RunUser = Cfg.Section("").Key("RUN_USER").MustString(user.CurrentUsername()) | RunUser = Cfg.Section("").Key("RUN_USER").MustString(user.CurrentUsername()) |
"strings" | "strings" | ||||
"time" | "time" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/markup" | "code.gitea.io/gitea/modules/markup" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | |||||
"gopkg.in/editorconfig/editorconfig-core-go.v1" | "gopkg.in/editorconfig/editorconfig-core-go.v1" | ||||
) | ) | ||||
"Safe": Safe, | "Safe": Safe, | ||||
"SafeJS": SafeJS, | "SafeJS": SafeJS, | ||||
"Str2html": Str2html, | "Str2html": Str2html, | ||||
"TimeSince": base.TimeSince, | |||||
"TimeSinceUnix": base.TimeSinceUnix, | |||||
"RawTimeSince": base.RawTimeSince, | |||||
"TimeSince": timeutil.TimeSince, | |||||
"TimeSinceUnix": timeutil.TimeSinceUnix, | |||||
"RawTimeSince": timeutil.RawTimeSince, | |||||
"FileSize": base.FileSize, | "FileSize": base.FileSize, | ||||
"Subtract": base.Subtract, | "Subtract": base.Subtract, | ||||
"EntryIcon": base.EntryIcon, | "EntryIcon": base.EntryIcon, |
// Copyright 2019 The Gitea 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 timeutil | |||||
import ( | |||||
"time" | |||||
"code.gitea.io/gitea/modules/setting" | |||||
) | |||||
var ( | |||||
langTimeFormats = map[string]string{ | |||||
"zh-CN": "2006年01月02日 15时04分05秒", | |||||
"en-US": time.RFC1123, | |||||
"lv-LV": "02.01.2006. 15:04:05", | |||||
} | |||||
) | |||||
// GetLangTimeFormat represents the default time format for the language | |||||
func GetLangTimeFormat(lang string) string { | |||||
return langTimeFormats[lang] | |||||
} | |||||
// GetTimeFormat represents the | |||||
func GetTimeFormat(lang string) string { | |||||
if setting.TimeFormat == "" { | |||||
format := GetLangTimeFormat(lang) | |||||
if format == "" { | |||||
format = time.RFC1123 | |||||
} | |||||
return format | |||||
} | |||||
return setting.TimeFormat | |||||
} |
// Copyright 2019 The Gitea 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 timeutil | |||||
import ( | |||||
"fmt" | |||||
"html/template" | |||||
"strings" | |||||
"time" | |||||
"code.gitea.io/gitea/modules/setting" | |||||
"github.com/Unknwon/i18n" | |||||
) | |||||
// Seconds-based time units | |||||
const ( | |||||
Minute = 60 | |||||
Hour = 60 * Minute | |||||
Day = 24 * Hour | |||||
Week = 7 * Day | |||||
Month = 30 * Day | |||||
Year = 12 * Month | |||||
) | |||||
func computeTimeDiff(diff int64, lang string) (int64, string) { | |||||
diffStr := "" | |||||
switch { | |||||
case diff <= 0: | |||||
diff = 0 | |||||
diffStr = i18n.Tr(lang, "tool.now") | |||||
case diff < 2: | |||||
diff = 0 | |||||
diffStr = i18n.Tr(lang, "tool.1s") | |||||
case diff < 1*Minute: | |||||
diffStr = i18n.Tr(lang, "tool.seconds", diff) | |||||
diff = 0 | |||||
case diff < 2*Minute: | |||||
diff -= 1 * Minute | |||||
diffStr = i18n.Tr(lang, "tool.1m") | |||||
case diff < 1*Hour: | |||||
diffStr = i18n.Tr(lang, "tool.minutes", diff/Minute) | |||||
diff -= diff / Minute * Minute | |||||
case diff < 2*Hour: | |||||
diff -= 1 * Hour | |||||
diffStr = i18n.Tr(lang, "tool.1h") | |||||
case diff < 1*Day: | |||||
diffStr = i18n.Tr(lang, "tool.hours", diff/Hour) | |||||
diff -= diff / Hour * Hour | |||||
case diff < 2*Day: | |||||
diff -= 1 * Day | |||||
diffStr = i18n.Tr(lang, "tool.1d") | |||||
case diff < 1*Week: | |||||
diffStr = i18n.Tr(lang, "tool.days", diff/Day) | |||||
diff -= diff / Day * Day | |||||
case diff < 2*Week: | |||||
diff -= 1 * Week | |||||
diffStr = i18n.Tr(lang, "tool.1w") | |||||
case diff < 1*Month: | |||||
diffStr = i18n.Tr(lang, "tool.weeks", diff/Week) | |||||
diff -= diff / Week * Week | |||||
case diff < 2*Month: | |||||
diff -= 1 * Month | |||||
diffStr = i18n.Tr(lang, "tool.1mon") | |||||
case diff < 1*Year: | |||||
diffStr = i18n.Tr(lang, "tool.months", diff/Month) | |||||
diff -= diff / Month * Month | |||||
case diff < 2*Year: | |||||
diff -= 1 * Year | |||||
diffStr = i18n.Tr(lang, "tool.1y") | |||||
default: | |||||
diffStr = i18n.Tr(lang, "tool.years", diff/Year) | |||||
diff -= (diff / Year) * Year | |||||
} | |||||
return diff, diffStr | |||||
} | |||||
// MinutesToFriendly returns a user friendly string with number of minutes | |||||
// converted to hours and minutes. | |||||
func MinutesToFriendly(minutes int, lang string) string { | |||||
duration := time.Duration(minutes) * time.Minute | |||||
return TimeSincePro(time.Now().Add(-duration), lang) | |||||
} | |||||
// TimeSincePro calculates the time interval and generate full user-friendly string. | |||||
func TimeSincePro(then time.Time, lang string) string { | |||||
return timeSincePro(then, time.Now(), lang) | |||||
} | |||||
func timeSincePro(then, now time.Time, lang string) string { | |||||
diff := now.Unix() - then.Unix() | |||||
if then.After(now) { | |||||
return i18n.Tr(lang, "tool.future") | |||||
} | |||||
if diff == 0 { | |||||
return i18n.Tr(lang, "tool.now") | |||||
} | |||||
var timeStr, diffStr string | |||||
for { | |||||
if diff == 0 { | |||||
break | |||||
} | |||||
diff, diffStr = computeTimeDiff(diff, lang) | |||||
timeStr += ", " + diffStr | |||||
} | |||||
return strings.TrimPrefix(timeStr, ", ") | |||||
} | |||||
func timeSince(then, now time.Time, lang string) string { | |||||
return timeSinceUnix(then.Unix(), now.Unix(), lang) | |||||
} | |||||
func timeSinceUnix(then, now int64, lang string) string { | |||||
lbl := "tool.ago" | |||||
diff := now - then | |||||
if then > now { | |||||
lbl = "tool.from_now" | |||||
diff = then - now | |||||
} | |||||
if diff <= 0 { | |||||
return i18n.Tr(lang, "tool.now") | |||||
} | |||||
_, diffStr := computeTimeDiff(diff, lang) | |||||
return i18n.Tr(lang, lbl, diffStr) | |||||
} | |||||
// RawTimeSince retrieves i18n key of time since t | |||||
func RawTimeSince(t time.Time, lang string) string { | |||||
return timeSince(t, time.Now(), lang) | |||||
} | |||||
// TimeSince calculates the time interval and generate user-friendly string. | |||||
func TimeSince(then time.Time, lang string) template.HTML { | |||||
return htmlTimeSince(then, time.Now(), lang) | |||||
} | |||||
func htmlTimeSince(then, now time.Time, lang string) template.HTML { | |||||
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`, | |||||
then.In(setting.DefaultUILocation).Format(GetTimeFormat(lang)), | |||||
timeSince(then, now, lang))) | |||||
} | |||||
// TimeSinceUnix calculates the time interval and generate user-friendly string. | |||||
func TimeSinceUnix(then TimeStamp, lang string) template.HTML { | |||||
return htmlTimeSinceUnix(then, TimeStamp(time.Now().Unix()), lang) | |||||
} | |||||
func htmlTimeSinceUnix(then, now TimeStamp, lang string) template.HTML { | |||||
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`, | |||||
then.FormatInLocation(GetTimeFormat(lang), setting.DefaultUILocation), | |||||
timeSinceUnix(int64(then), int64(now), lang))) | |||||
} |
// Copyright 2019 The Gitea 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 timeutil | |||||
import ( | |||||
"os" | |||||
"testing" | |||||
"time" | |||||
"code.gitea.io/gitea/modules/setting" | |||||
"github.com/Unknwon/i18n" | |||||
macaroni18n "github.com/go-macaron/i18n" | |||||
"github.com/stretchr/testify/assert" | |||||
) | |||||
var BaseDate time.Time | |||||
// time durations | |||||
const ( | |||||
DayDur = 24 * time.Hour | |||||
WeekDur = 7 * DayDur | |||||
MonthDur = 30 * DayDur | |||||
YearDur = 12 * MonthDur | |||||
) | |||||
func TestMain(m *testing.M) { | |||||
// setup | |||||
macaroni18n.I18n(macaroni18n.Options{ | |||||
Directory: "../../options/locale/", | |||||
DefaultLang: "en-US", | |||||
Langs: []string{"en-US"}, | |||||
Names: []string{"english"}, | |||||
}) | |||||
BaseDate = time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) | |||||
// run the tests | |||||
retVal := m.Run() | |||||
os.Exit(retVal) | |||||
} | |||||
func TestTimeSince(t *testing.T) { | |||||
assert.Equal(t, "now", timeSince(BaseDate, BaseDate, "en")) | |||||
// test that each diff in `diffs` yields the expected string | |||||
test := func(expected string, diffs ...time.Duration) { | |||||
for _, diff := range diffs { | |||||
actual := timeSince(BaseDate, BaseDate.Add(diff), "en") | |||||
assert.Equal(t, i18n.Tr("en", "tool.ago", expected), actual) | |||||
actual = timeSince(BaseDate.Add(diff), BaseDate, "en") | |||||
assert.Equal(t, i18n.Tr("en", "tool.from_now", expected), actual) | |||||
} | |||||
} | |||||
test("1 second", time.Second, time.Second+50*time.Millisecond) | |||||
test("2 seconds", 2*time.Second, 2*time.Second+50*time.Millisecond) | |||||
test("1 minute", time.Minute, time.Minute+30*time.Second) | |||||
test("2 minutes", 2*time.Minute, 2*time.Minute+30*time.Second) | |||||
test("1 hour", time.Hour, time.Hour+30*time.Minute) | |||||
test("2 hours", 2*time.Hour, 2*time.Hour+30*time.Minute) | |||||
test("1 day", DayDur, DayDur+12*time.Hour) | |||||
test("2 days", 2*DayDur, 2*DayDur+12*time.Hour) | |||||
test("1 week", WeekDur, WeekDur+3*DayDur) | |||||
test("2 weeks", 2*WeekDur, 2*WeekDur+3*DayDur) | |||||
test("1 month", MonthDur, MonthDur+15*DayDur) | |||||
test("2 months", 2*MonthDur, 2*MonthDur+15*DayDur) | |||||
test("1 year", YearDur, YearDur+6*MonthDur) | |||||
test("2 years", 2*YearDur, 2*YearDur+6*MonthDur) | |||||
} | |||||
func TestTimeSincePro(t *testing.T) { | |||||
assert.Equal(t, "now", timeSincePro(BaseDate, BaseDate, "en")) | |||||
// test that a difference of `diff` yields the expected string | |||||
test := func(expected string, diff time.Duration) { | |||||
actual := timeSincePro(BaseDate, BaseDate.Add(diff), "en") | |||||
assert.Equal(t, expected, actual) | |||||
assert.Equal(t, "future", timeSincePro(BaseDate.Add(diff), BaseDate, "en")) | |||||
} | |||||
test("1 second", time.Second) | |||||
test("2 seconds", 2*time.Second) | |||||
test("1 minute", time.Minute) | |||||
test("1 minute, 1 second", time.Minute+time.Second) | |||||
test("1 minute, 59 seconds", time.Minute+59*time.Second) | |||||
test("2 minutes", 2*time.Minute) | |||||
test("1 hour", time.Hour) | |||||
test("1 hour, 1 second", time.Hour+time.Second) | |||||
test("1 hour, 59 minutes, 59 seconds", time.Hour+59*time.Minute+59*time.Second) | |||||
test("2 hours", 2*time.Hour) | |||||
test("1 day", DayDur) | |||||
test("1 day, 23 hours, 59 minutes, 59 seconds", | |||||
DayDur+23*time.Hour+59*time.Minute+59*time.Second) | |||||
test("2 days", 2*DayDur) | |||||
test("1 week", WeekDur) | |||||
test("2 weeks", 2*WeekDur) | |||||
test("1 month", MonthDur) | |||||
test("3 months", 3*MonthDur) | |||||
test("1 year", YearDur) | |||||
test("2 years, 3 months, 1 week, 2 days, 4 hours, 12 minutes, 17 seconds", | |||||
2*YearDur+3*MonthDur+WeekDur+2*DayDur+4*time.Hour+ | |||||
12*time.Minute+17*time.Second) | |||||
} | |||||
func TestHtmlTimeSince(t *testing.T) { | |||||
setting.TimeFormat = time.UnixDate | |||||
setting.DefaultUILocation = time.UTC | |||||
// test that `diff` yields a result containing `expected` | |||||
test := func(expected string, diff time.Duration) { | |||||
actual := htmlTimeSince(BaseDate, BaseDate.Add(diff), "en") | |||||
assert.Contains(t, actual, `title="Sat Jan 1 00:00:00 UTC 2000"`) | |||||
assert.Contains(t, actual, expected) | |||||
} | |||||
test("1 second", time.Second) | |||||
test("3 minutes", 3*time.Minute+5*time.Second) | |||||
test("1 day", DayDur+18*time.Hour) | |||||
test("1 week", WeekDur+6*DayDur) | |||||
test("3 months", 3*MonthDur+3*WeekDur) | |||||
test("2 years", 2*YearDur) | |||||
test("3 years", 3*YearDur+11*MonthDur+4*WeekDur) | |||||
} | |||||
func TestComputeTimeDiff(t *testing.T) { | |||||
// test that for each offset in offsets, | |||||
// computeTimeDiff(base + offset) == (offset, str) | |||||
test := func(base int64, str string, offsets ...int64) { | |||||
for _, offset := range offsets { | |||||
diff, diffStr := computeTimeDiff(base+offset, "en") | |||||
assert.Equal(t, offset, diff) | |||||
assert.Equal(t, str, diffStr) | |||||
} | |||||
} | |||||
test(0, "now", 0) | |||||
test(1, "1 second", 0) | |||||
test(2, "2 seconds", 0) | |||||
test(Minute, "1 minute", 0, 1, 30, Minute-1) | |||||
test(2*Minute, "2 minutes", 0, Minute-1) | |||||
test(Hour, "1 hour", 0, 1, Hour-1) | |||||
test(5*Hour, "5 hours", 0, Hour-1) | |||||
test(Day, "1 day", 0, 1, Day-1) | |||||
test(5*Day, "5 days", 0, Day-1) | |||||
test(Week, "1 week", 0, 1, Week-1) | |||||
test(3*Week, "3 weeks", 0, 4*Day+25000) | |||||
test(Month, "1 month", 0, 1, Month-1) | |||||
test(10*Month, "10 months", 0, Month-1) | |||||
test(Year, "1 year", 0, Year-1) | |||||
test(3*Year, "3 years", 0, Year-1) | |||||
} | |||||
func TestMinutesToFriendly(t *testing.T) { | |||||
// test that a number of minutes yields the expected string | |||||
test := func(expected string, minutes int) { | |||||
actual := MinutesToFriendly(minutes, "en") | |||||
assert.Equal(t, expected, actual) | |||||
} | |||||
test("1 minute", 1) | |||||
test("2 minutes", 2) | |||||
test("1 hour", 60) | |||||
test("1 hour, 1 minute", 61) | |||||
test("1 hour, 2 minutes", 62) | |||||
test("2 hours", 120) | |||||
} |
// Use of this source code is governed by a MIT-style | // Use of this source code is governed by a MIT-style | ||||
// license that can be found in the LICENSE file. | // license that can be found in the LICENSE file. | ||||
package util | |||||
package timeutil | |||||
import ( | import ( | ||||
"time" | "time" | ||||
// AsTime convert timestamp as time.Time in Local locale | // AsTime convert timestamp as time.Time in Local locale | ||||
func (ts TimeStamp) AsTime() (tm time.Time) { | func (ts TimeStamp) AsTime() (tm time.Time) { | ||||
tm = time.Unix(int64(ts), 0).In(setting.UILocation) | |||||
return ts.AsTimeInLocation(setting.DefaultUILocation) | |||||
} | |||||
// AsTimeInLocation convert timestamp as time.Time in Local locale | |||||
func (ts TimeStamp) AsTimeInLocation(loc *time.Location) (tm time.Time) { | |||||
tm = time.Unix(int64(ts), 0).In(loc) | |||||
return | return | ||||
} | } | ||||
// AsTimePtr convert timestamp as *time.Time in Local locale | // AsTimePtr convert timestamp as *time.Time in Local locale | ||||
func (ts TimeStamp) AsTimePtr() *time.Time { | func (ts TimeStamp) AsTimePtr() *time.Time { | ||||
tm := time.Unix(int64(ts), 0).In(setting.UILocation) | |||||
return ts.AsTimePtrInLocation(setting.DefaultUILocation) | |||||
} | |||||
// AsTimePtrInLocation convert timestamp as *time.Time in customize location | |||||
func (ts TimeStamp) AsTimePtrInLocation(loc *time.Location) *time.Time { | |||||
tm := time.Unix(int64(ts), 0).In(loc) | |||||
return &tm | return &tm | ||||
} | } | ||||
// Format formats timestamp as | |||||
// Format formats timestamp as given format | |||||
func (ts TimeStamp) Format(f string) string { | func (ts TimeStamp) Format(f string) string { | ||||
return ts.AsTime().Format(f) | |||||
return ts.FormatInLocation(f, setting.DefaultUILocation) | |||||
} | |||||
// FormatInLocation formats timestamp as given format with spiecific location | |||||
func (ts TimeStamp) FormatInLocation(f string, loc *time.Location) string { | |||||
return ts.AsTimeInLocation(loc).Format(f) | |||||
} | } | ||||
// FormatLong formats as RFC1123Z | // FormatLong formats as RFC1123Z | ||||
// IsZero is zero time | // IsZero is zero time | ||||
func (ts TimeStamp) IsZero() bool { | func (ts TimeStamp) IsZero() bool { | ||||
return ts.AsTime().IsZero() | |||||
return ts.AsTimeInLocation(time.Local).IsZero() | |||||
} | } |
// Show exact time | // Show exact time | ||||
$('.time-since').each(function () { | $('.time-since').each(function () { | ||||
const time = new Date($(this).attr('title')) | |||||
if (!isNaN(time)){ | |||||
$(this).attr('title', time.toLocaleString()) | |||||
} | |||||
$(this).addClass('poping up').attr('data-content', $(this).attr('title')).attr('data-variation', 'inverted tiny').attr('title', ''); | $(this).addClass('poping up').attr('data-content', $(this).attr('title')).attr('data-variation', 'inverted tiny').attr('title', ''); | ||||
}); | }); | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/process" | "code.gitea.io/gitea/modules/process" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
const ( | const ( | ||||
} | } | ||||
func updateSystemStatus() { | func updateSystemStatus() { | ||||
sysStatus.Uptime = base.TimeSincePro(startTime, "en") | |||||
sysStatus.Uptime = timeutil.TimeSincePro(startTime, "en") | |||||
m := new(runtime.MemStats) | m := new(runtime.MemStats) | ||||
runtime.ReadMemStats(m) | runtime.ReadMemStats(m) |
issue_indexer "code.gitea.io/gitea/modules/indexer/issues" | issue_indexer "code.gitea.io/gitea/modules/indexer/issues" | ||||
"code.gitea.io/gitea/modules/notification" | "code.gitea.io/gitea/modules/notification" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
// "201": | // "201": | ||||
// "$ref": "#/responses/Issue" | // "$ref": "#/responses/Issue" | ||||
var deadlineUnix util.TimeStamp | |||||
var deadlineUnix timeutil.TimeStamp | |||||
if form.Deadline != nil && ctx.Repo.CanWrite(models.UnitTypeIssues) { | if form.Deadline != nil && ctx.Repo.CanWrite(models.UnitTypeIssues) { | ||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix()) | |||||
deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix()) | |||||
} | } | ||||
issue := &models.Issue{ | issue := &models.Issue{ | ||||
} | } | ||||
// Update the deadline | // Update the deadline | ||||
var deadlineUnix util.TimeStamp | |||||
var deadlineUnix timeutil.TimeStamp | |||||
if form.Deadline != nil && !form.Deadline.IsZero() && ctx.Repo.CanWrite(models.UnitTypeIssues) { | if form.Deadline != nil && !form.Deadline.IsZero() && ctx.Repo.CanWrite(models.UnitTypeIssues) { | ||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix()) | |||||
deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix()) | |||||
} | } | ||||
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | ||||
return | return | ||||
} | } | ||||
var deadlineUnix util.TimeStamp | |||||
var deadlineUnix timeutil.TimeStamp | |||||
var deadline time.Time | var deadline time.Time | ||||
if form.Deadline != nil && !form.Deadline.IsZero() { | if form.Deadline != nil && !form.Deadline.IsZero() { | ||||
deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(), | deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(), | ||||
23, 59, 59, 0, form.Deadline.Location()) | 23, 59, 59, 0, form.Deadline.Location()) | ||||
deadlineUnix = util.TimeStamp(deadline.Unix()) | |||||
deadlineUnix = timeutil.TimeStamp(deadline.Unix()) | |||||
} | } | ||||
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { |
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/util" | |||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// ListMilestones list milestones for a repository | // ListMilestones list milestones for a repository | ||||
RepoID: ctx.Repo.Repository.ID, | RepoID: ctx.Repo.Repository.ID, | ||||
Name: form.Title, | Name: form.Title, | ||||
Content: form.Description, | Content: form.Description, | ||||
DeadlineUnix: util.TimeStamp(form.Deadline.Unix()), | |||||
DeadlineUnix: timeutil.TimeStamp(form.Deadline.Unix()), | |||||
} | } | ||||
if err := models.NewMilestone(milestone); err != nil { | if err := models.NewMilestone(milestone); err != nil { | ||||
milestone.Content = *form.Description | milestone.Content = *form.Description | ||||
} | } | ||||
if form.Deadline != nil && !form.Deadline.IsZero() { | if form.Deadline != nil && !form.Deadline.IsZero() { | ||||
milestone.DeadlineUnix = util.TimeStamp(form.Deadline.Unix()) | |||||
milestone.DeadlineUnix = timeutil.TimeStamp(form.Deadline.Unix()) | |||||
} | } | ||||
if err := models.UpdateMilestone(milestone); err != nil { | if err := models.UpdateMilestone(milestone); err != nil { |
"code.gitea.io/gitea/modules/notification" | "code.gitea.io/gitea/modules/notification" | ||||
"code.gitea.io/gitea/modules/pull" | "code.gitea.io/gitea/modules/pull" | ||||
api "code.gitea.io/gitea/modules/structs" | api "code.gitea.io/gitea/modules/structs" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// ListPullRequests returns a list of all PRs | // ListPullRequests returns a list of all PRs | ||||
return | return | ||||
} | } | ||||
var deadlineUnix util.TimeStamp | |||||
var deadlineUnix timeutil.TimeStamp | |||||
if form.Deadline != nil { | if form.Deadline != nil { | ||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix()) | |||||
deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix()) | |||||
} | } | ||||
maxIndex, err := models.GetMaxIndexOfIssue(repo.ID) | maxIndex, err := models.GetMaxIndexOfIssue(repo.ID) | ||||
} | } | ||||
// Update Deadline | // Update Deadline | ||||
var deadlineUnix util.TimeStamp | |||||
var deadlineUnix timeutil.TimeStamp | |||||
if form.Deadline != nil && !form.Deadline.IsZero() { | if form.Deadline != nil && !form.Deadline.IsZero() { | ||||
deadlineUnix = util.TimeStamp(form.Deadline.Unix()) | |||||
deadlineUnix = timeutil.TimeStamp(form.Deadline.Unix()) | |||||
} | } | ||||
if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { | if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil { |
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// TemplatePreview render for previewing the indicated template | // TemplatePreview render for previewing the indicated template | ||||
ctx.Data["AppVer"] = setting.AppVer | ctx.Data["AppVer"] = setting.AppVer | ||||
ctx.Data["AppUrl"] = setting.AppURL | ctx.Data["AppUrl"] = setting.AppURL | ||||
ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374" | ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374" | ||||
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["CurDbValue"] = "" | ctx.Data["CurDbValue"] = "" | ||||
ctx.HTML(200, base.TplName(ctx.Params("*"))) | ctx.HTML(200, base.TplName(ctx.Params("*"))) |
import ( | import ( | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
macaron "gopkg.in/macaron.v1" | macaron "gopkg.in/macaron.v1" | ||||
) | ) | ||||
}) | }) | ||||
return | return | ||||
} | } | ||||
deployKey.UpdatedUnix = util.TimeStampNow() | |||||
deployKey.UpdatedUnix = timeutil.TimeStampNow() | |||||
if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil { | if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil { | ||||
ctx.JSON(500, map[string]interface{}{ | ctx.JSON(500, map[string]interface{}{ | ||||
"err": err.Error(), | "err": err.Error(), |
"strings" | "strings" | ||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/markup" | "code.gitea.io/gitea/modules/markup" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
const ( | const ( | ||||
if index == 0 { | if index == 0 { | ||||
// User avatar image | // User avatar image | ||||
avatar := "" | avatar := "" | ||||
commitSince := base.TimeSinceUnix(util.TimeStamp(commit.Author.When.Unix()), ctx.Data["Lang"].(string)) | |||||
commitSince := timeutil.TimeSinceUnix(timeutil.TimeStamp(commit.Author.When.Unix()), ctx.Data["Lang"].(string)) | |||||
if commit.User != nil { | if commit.User != nil { | ||||
authorName := commit.Author.Name | authorName := commit.Author.Name | ||||
if len(commit.User.FullName) > 0 { | if len(commit.User.FullName) > 0 { |
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
// HTTP implmentation git smart HTTP protocol | // HTTP implmentation git smart HTTP protocol | ||||
return | return | ||||
} | } | ||||
} | } | ||||
token.UpdatedUnix = util.TimeStampNow() | |||||
token.UpdatedUnix = timeutil.TimeStampNow() | |||||
if err = models.UpdateAccessToken(token); err != nil { | if err = models.UpdateAccessToken(token); err != nil { | ||||
ctx.ServerError("UpdateAccessToken", err) | ctx.ServerError("UpdateAccessToken", err) | ||||
} | } |
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/markup/markdown" | "code.gitea.io/gitea/modules/markup/markdown" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
) | ) | ||||
RepoID: ctx.Repo.Repository.ID, | RepoID: ctx.Repo.Repository.ID, | ||||
Name: form.Title, | Name: form.Title, | ||||
Content: form.Content, | Content: form.Content, | ||||
DeadlineUnix: util.TimeStamp(deadline.Unix()), | |||||
DeadlineUnix: timeutil.TimeStamp(deadline.Unix()), | |||||
}); err != nil { | }); err != nil { | ||||
ctx.ServerError("NewMilestone", err) | ctx.ServerError("NewMilestone", err) | ||||
return | return | ||||
} | } | ||||
m.Name = form.Title | m.Name = form.Title | ||||
m.Content = form.Content | m.Content = form.Content | ||||
m.DeadlineUnix = util.TimeStamp(deadline.Unix()) | |||||
m.DeadlineUnix = timeutil.TimeStamp(deadline.Unix()) | |||||
if err = models.UpdateMilestone(m); err != nil { | if err = models.UpdateMilestone(m); err != nil { | ||||
ctx.ServerError("UpdateMilestone", err) | ctx.ServerError("UpdateMilestone", err) | ||||
return | return | ||||
ctx.Redirect(ctx.Repo.RepoLink + "/milestones?state=open") | ctx.Redirect(ctx.Repo.RepoLink + "/milestones?state=open") | ||||
case "close": | case "close": | ||||
if !m.IsClosed { | if !m.IsClosed { | ||||
m.ClosedDateUnix = util.TimeStampNow() | |||||
m.ClosedDateUnix = timeutil.TimeStampNow() | |||||
if err = models.ChangeMilestoneStatus(m, true); err != nil { | if err = models.ChangeMilestoneStatus(m, true); err != nil { | ||||
ctx.ServerError("ChangeMilestoneStatus", err) | ctx.ServerError("ChangeMilestoneStatus", err) | ||||
return | return |
"strings" | "strings" | ||||
"time" | "time" | ||||
"github.com/Unknwon/com" | |||||
"mvdan.cc/xurls/v2" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/auth" | "code.gitea.io/gitea/modules/auth" | ||||
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/validation" | "code.gitea.io/gitea/modules/validation" | ||||
"code.gitea.io/gitea/routers/utils" | "code.gitea.io/gitea/routers/utils" | ||||
"github.com/Unknwon/com" | |||||
"mvdan.cc/xurls/v2" | |||||
) | ) | ||||
const ( | const ( | ||||
ctx.Repo.Mirror.EnablePrune = form.EnablePrune | ctx.Repo.Mirror.EnablePrune = form.EnablePrune | ||||
ctx.Repo.Mirror.Interval = interval | ctx.Repo.Mirror.Interval = interval | ||||
if interval != 0 { | if interval != 0 { | ||||
ctx.Repo.Mirror.NextUpdateUnix = util.TimeStampNow().AddDuration(interval) | |||||
ctx.Repo.Mirror.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(interval) | |||||
} else { | } else { | ||||
ctx.Repo.Mirror.NextUpdateUnix = 0 | ctx.Repo.Mirror.NextUpdateUnix = 0 | ||||
} | } |
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/markup" | "code.gitea.io/gitea/modules/markup" | ||||
"code.gitea.io/gitea/modules/markup/markdown" | "code.gitea.io/gitea/modules/markup/markdown" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
) | ) | ||||
type PageMeta struct { | type PageMeta struct { | ||||
Name string | Name string | ||||
SubURL string | SubURL string | ||||
UpdatedUnix util.TimeStamp | |||||
UpdatedUnix timeutil.TimeStamp | |||||
} | } | ||||
// findEntryForFile finds the tree entry for a target filepath. | // findEntryForFile finds the tree entry for a target filepath. | ||||
pages = append(pages, PageMeta{ | pages = append(pages, PageMeta{ | ||||
Name: wikiName, | Name: wikiName, | ||||
SubURL: models.WikiNameToSubURL(wikiName), | SubURL: models.WikiNameToSubURL(wikiName), | ||||
UpdatedUnix: util.TimeStamp(c.Author.When.Unix()), | |||||
UpdatedUnix: timeutil.TimeStamp(c.Author.When.Unix()), | |||||
}) | }) | ||||
} | } | ||||
ctx.Data["Pages"] = pages | ctx.Data["Pages"] = pages |
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/recaptcha" | "code.gitea.io/gitea/modules/recaptcha" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"code.gitea.io/gitea/modules/util" | "code.gitea.io/gitea/modules/util" | ||||
"github.com/go-macaron/captcha" | "github.com/go-macaron/captcha" | ||||
models.SendActivateAccountMail(ctx.Context, u) | models.SendActivateAccountMail(ctx.Context, u) | ||||
ctx.Data["IsSendRegisterMail"] = true | ctx.Data["IsSendRegisterMail"] = true | ||||
ctx.Data["Email"] = u.Email | ctx.Data["Email"] = u.Email | ||||
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
ctx.HTML(200, TplActivate) | ctx.HTML(200, TplActivate) | ||||
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { | if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { | ||||
models.SendActivateAccountMail(ctx.Context, u) | models.SendActivateAccountMail(ctx.Context, u) | ||||
ctx.Data["IsSendRegisterMail"] = true | ctx.Data["IsSendRegisterMail"] = true | ||||
ctx.Data["Email"] = u.Email | ctx.Data["Email"] = u.Email | ||||
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
ctx.HTML(200, TplActivate) | ctx.HTML(200, TplActivate) | ||||
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { | if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { | ||||
if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { | if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { | ||||
ctx.Data["ResendLimited"] = true | ctx.Data["ResendLimited"] = true | ||||
} else { | } else { | ||||
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
models.SendActivateAccountMail(ctx.Context, ctx.User) | models.SendActivateAccountMail(ctx.Context, ctx.User) | ||||
if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { | if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { | ||||
u, err := models.GetUserByEmail(email) | u, err := models.GetUserByEmail(email) | ||||
if err != nil { | if err != nil { | ||||
if models.IsErrUserNotExist(err) { | if models.IsErrUserNotExist(err) { | ||||
ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["IsResetSent"] = true | ctx.Data["IsResetSent"] = true | ||||
ctx.HTML(200, tplForgotPassword) | ctx.HTML(200, tplForgotPassword) | ||||
return | return | ||||
log.Error("Set cache(MailResendLimit) fail: %v", err) | log.Error("Set cache(MailResendLimit) fail: %v", err) | ||||
} | } | ||||
ctx.Data["ResetPwdCodeLives"] = base.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["ResetPwdCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["IsResetSent"] = true | ctx.Data["IsResetSent"] = true | ||||
ctx.HTML(200, tplForgotPassword) | ctx.HTML(200, tplForgotPassword) | ||||
} | } |
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/recaptcha" | "code.gitea.io/gitea/modules/recaptcha" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/go-macaron/captcha" | "github.com/go-macaron/captcha" | ||||
) | ) | ||||
models.SendActivateAccountMail(ctx.Context, u) | models.SendActivateAccountMail(ctx.Context, u) | ||||
ctx.Data["IsSendRegisterMail"] = true | ctx.Data["IsSendRegisterMail"] = true | ||||
ctx.Data["Email"] = u.Email | ctx.Data["Email"] = u.Email | ||||
ctx.Data["ActiveCodeLives"] = base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()) | |||||
ctx.HTML(200, TplActivate) | ctx.HTML(200, TplActivate) | ||||
if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { | if err := ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { |
import ( | import ( | ||||
"encoding/base64" | "encoding/base64" | ||||
"fmt" | "fmt" | ||||
"github.com/go-macaron/binding" | |||||
"net/url" | "net/url" | ||||
"strings" | "strings" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/util" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"github.com/dgrijalva/jwt-go" | "github.com/dgrijalva/jwt-go" | ||||
"github.com/go-macaron/binding" | |||||
) | ) | ||||
const ( | const ( | ||||
} | } | ||||
} | } | ||||
// generate access token to access the API | // generate access token to access the API | ||||
expirationDate := util.TimeStampNow().Add(setting.OAuth2.AccessTokenExpirationTime) | |||||
expirationDate := timeutil.TimeStampNow().Add(setting.OAuth2.AccessTokenExpirationTime) | |||||
accessToken := &models.OAuth2Token{ | accessToken := &models.OAuth2Token{ | ||||
GrantID: grant.ID, | GrantID: grant.ID, | ||||
Type: models.TypeAccessToken, | Type: models.TypeAccessToken, | ||||
} | } | ||||
// generate refresh token to request an access token after it expired later | // generate refresh token to request an access token after it expired later | ||||
refreshExpirationDate := util.TimeStampNow().Add(setting.OAuth2.RefreshTokenExpirationTime * 60 * 60).AsTime().Unix() | |||||
refreshExpirationDate := timeutil.TimeStampNow().Add(setting.OAuth2.RefreshTokenExpirationTime * 60 * 60).AsTime().Unix() | |||||
refreshToken := &models.OAuth2Token{ | refreshToken := &models.OAuth2Token{ | ||||
GrantID: grant.ID, | GrantID: grant.ID, | ||||
Counter: grant.Counter, | Counter: grant.Counter, |
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | |||||
) | ) | ||||
const ( | const ( | ||||
if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { | if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { | ||||
log.Error("Set cache(MailResendLimit) fail: %v", err) | log.Error("Set cache(MailResendLimit) fail: %v", err) | ||||
} | } | ||||
ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, base.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()))) | |||||
ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language()))) | |||||
} else { | } else { | ||||
ctx.Flash.Success(ctx.Tr("settings.add_email_success")) | ctx.Flash.Success(ctx.Tr("settings.add_email_success")) | ||||
} | } |
"description": "TimeStamp defines a timestamp", | "description": "TimeStamp defines a timestamp", | ||||
"type": "integer", | "type": "integer", | ||||
"format": "int64", | "format": "int64", | ||||
"x-go-package": "code.gitea.io/gitea/modules/util" | |||||
"x-go-package": "code.gitea.io/gitea/modules/timeutil" | |||||
}, | }, | ||||
"TrackedTime": { | "TrackedTime": { | ||||
"description": "TrackedTime worked time for an issue / pr", | "description": "TrackedTime worked time for an issue / pr", |