2014-02-19 02:31:16 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2014-03-08 02:22:15 +04:00
package base
2014-02-19 02:31:16 +04:00
import (
2014-03-16 20:07:35 +04:00
"bytes"
2014-02-19 02:31:16 +04:00
"crypto/md5"
"encoding/hex"
2014-03-16 19:30:35 +04:00
"encoding/json"
2014-03-14 10:32:11 +04:00
"fmt"
2014-03-15 20:29:49 +04:00
"math"
2014-03-15 11:28:06 +04:00
"strings"
2014-03-14 10:32:11 +04:00
"time"
2014-02-19 02:31:16 +04:00
)
// Encode string to md5 hex value
func EncodeMd5 ( str string ) string {
m := md5 . New ( )
m . Write ( [ ] byte ( str ) )
return hex . EncodeToString ( m . Sum ( nil ) )
}
2014-03-14 10:32:11 +04:00
2014-03-17 08:57:18 +04:00
// AvatarLink returns avatar link by given e-mail.
func AvatarLink ( email string ) string {
return "http://1.gravatar.com/avatar/" + EncodeMd5 ( email )
}
2014-03-14 10:32:11 +04:00
// Seconds-based time units
const (
Minute = 60
Hour = 60 * Minute
Day = 24 * Hour
Week = 7 * Day
Month = 30 * Day
Year = 12 * Month
)
// TimeSince calculates the time interval and generate user-friendly string.
func TimeSince ( then time . Time ) string {
now := time . Now ( )
lbl := "ago"
diff := now . Unix ( ) - then . Unix ( )
if then . After ( now ) {
lbl = "from now"
diff = then . Unix ( ) - now . Unix ( )
}
switch {
case diff <= 0 :
return "now"
case diff <= 2 :
return fmt . Sprintf ( "1 second %s" , lbl )
case diff < 1 * Minute :
return fmt . Sprintf ( "%d seconds %s" , diff , lbl )
case diff < 2 * Minute :
return fmt . Sprintf ( "1 minute %s" , lbl )
case diff < 1 * Hour :
return fmt . Sprintf ( "%d minutes %s" , diff / Minute , lbl )
case diff < 2 * Hour :
return fmt . Sprintf ( "1 hour %s" , lbl )
case diff < 1 * Day :
return fmt . Sprintf ( "%d hours %s" , diff / Hour , lbl )
case diff < 2 * Day :
return fmt . Sprintf ( "1 day %s" , lbl )
case diff < 1 * Week :
return fmt . Sprintf ( "%d days %s" , diff / Day , lbl )
case diff < 2 * Week :
return fmt . Sprintf ( "1 week %s" , lbl )
case diff < 1 * Month :
return fmt . Sprintf ( "%d weeks %s" , diff / Week , lbl )
case diff < 2 * Month :
return fmt . Sprintf ( "1 month %s" , lbl )
case diff < 1 * Year :
return fmt . Sprintf ( "%d months %s" , diff / Month , lbl )
case diff < 18 * Month :
return fmt . Sprintf ( "1 year %s" , lbl )
}
return then . String ( )
}
2014-03-15 03:34:59 +04:00
2014-03-15 20:29:49 +04:00
const (
Byte = 1
KByte = Byte * 1024
MByte = KByte * 1024
GByte = MByte * 1024
TByte = GByte * 1024
PByte = TByte * 1024
EByte = PByte * 1024
)
var bytesSizeTable = map [ string ] uint64 {
"b" : Byte ,
"kb" : KByte ,
"mb" : MByte ,
"gb" : GByte ,
"tb" : TByte ,
"pb" : PByte ,
"eb" : EByte ,
}
func logn ( n , b float64 ) float64 {
return math . Log ( n ) / math . Log ( b )
}
func humanateBytes ( s uint64 , base float64 , sizes [ ] string ) string {
if s < 10 {
return fmt . Sprintf ( "%dB" , s )
}
e := math . Floor ( logn ( float64 ( s ) , base ) )
suffix := sizes [ int ( e ) ]
val := float64 ( s ) / math . Pow ( base , math . Floor ( e ) )
f := "%.0f"
if val < 10 {
f = "%.1f"
}
return fmt . Sprintf ( f + "%s" , val , suffix )
}
// FileSize calculates the file size and generate user-friendly string.
2014-03-15 20:31:12 +04:00
func FileSize ( s int64 ) string {
2014-03-15 20:29:49 +04:00
sizes := [ ] string { "B" , "KB" , "MB" , "GB" , "TB" , "PB" , "EB" }
return humanateBytes ( uint64 ( s ) , 1024 , sizes )
}
2014-03-15 03:34:59 +04:00
// Subtract deals with subtraction of all types of number.
func Subtract ( left interface { } , right interface { } ) interface { } {
var rleft , rright int64
var fleft , fright float64
var isInt bool = true
switch left . ( type ) {
case int :
rleft = int64 ( left . ( int ) )
case int8 :
rleft = int64 ( left . ( int8 ) )
case int16 :
rleft = int64 ( left . ( int16 ) )
case int32 :
rleft = int64 ( left . ( int32 ) )
case int64 :
rleft = left . ( int64 )
case float32 :
fleft = float64 ( left . ( float32 ) )
isInt = false
case float64 :
fleft = left . ( float64 )
isInt = false
}
switch right . ( type ) {
case int :
rright = int64 ( right . ( int ) )
case int8 :
rright = int64 ( right . ( int8 ) )
case int16 :
rright = int64 ( right . ( int16 ) )
case int32 :
rright = int64 ( right . ( int32 ) )
case int64 :
rright = right . ( int64 )
case float32 :
fright = float64 ( left . ( float32 ) )
isInt = false
case float64 :
fleft = left . ( float64 )
isInt = false
}
if isInt {
return rleft - rright
} else {
return fleft + float64 ( rleft ) - ( fright + float64 ( rright ) )
}
}
2014-03-15 08:50:51 +04:00
2014-03-15 11:28:06 +04:00
// DateFormat pattern rules.
var datePatterns = [ ] string {
// year
"Y" , "2006" , // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
"y" , "06" , //A two digit representation of a year Examples: 99 or 03
// month
"m" , "01" , // Numeric representation of a month, with leading zeros 01 through 12
"n" , "1" , // Numeric representation of a month, without leading zeros 1 through 12
"M" , "Jan" , // A short textual representation of a month, three letters Jan through Dec
"F" , "January" , // A full textual representation of a month, such as January or March January through December
// day
"d" , "02" , // Day of the month, 2 digits with leading zeros 01 to 31
"j" , "2" , // Day of the month without leading zeros 1 to 31
// week
"D" , "Mon" , // A textual representation of a day, three letters Mon through Sun
"l" , "Monday" , // A full textual representation of the day of the week Sunday through Saturday
// time
"g" , "3" , // 12-hour format of an hour without leading zeros 1 through 12
"G" , "15" , // 24-hour format of an hour without leading zeros 0 through 23
"h" , "03" , // 12-hour format of an hour with leading zeros 01 through 12
"H" , "15" , // 24-hour format of an hour with leading zeros 00 through 23
"a" , "pm" , // Lowercase Ante meridiem and Post meridiem am or pm
"A" , "PM" , // Uppercase Ante meridiem and Post meridiem AM or PM
"i" , "04" , // Minutes with leading zeros 00 to 59
"s" , "05" , // Seconds, with leading zeros 00 through 59
// time zone
"T" , "MST" ,
"P" , "-07:00" ,
"O" , "-0700" ,
// RFC 2822
"r" , time . RFC1123Z ,
}
// Parse Date use PHP time format.
func DateParse ( dateString , format string ) ( time . Time , error ) {
replacer := strings . NewReplacer ( datePatterns ... )
format = replacer . Replace ( format )
return time . ParseInLocation ( format , dateString , time . Local )
}
// Date takes a PHP like date func to Go's time format.
func DateFormat ( t time . Time , format string ) string {
replacer := strings . NewReplacer ( datePatterns ... )
format = replacer . Replace ( format )
return t . Format ( format )
}
2014-03-15 08:50:51 +04:00
type Actioner interface {
GetOpType ( ) int
GetActUserName ( ) string
GetRepoName ( ) string
2014-03-16 19:30:35 +04:00
GetContent ( ) string
2014-03-15 08:50:51 +04:00
}
// ActionIcon accepts a int that represents action operation type
// and returns a icon class name.
func ActionIcon ( opType int ) string {
switch opType {
case 1 : // Create repository.
return "plus-circle"
2014-03-16 19:30:35 +04:00
case 5 : // Commit repository.
return "arrow-circle-o-right"
2014-03-15 08:50:51 +04:00
default :
return "invalid type"
}
}
const (
2014-03-16 20:07:35 +04:00
TPL_CREATE_REPO = ` <a href="/user/%s">%s</a> created repository <a href="/%s/%s">%s</a> `
TPL_COMMIT_REPO = ` <a href="/user/%s">%s</a> pushed to <a href="/%s/%s/tree/%s">%s</a> at <a href="/%s/%s">%s/%s</a>%s `
TPL_COMMIT_REPO_LI = ` <div><img id="gogs-user-avatar-commit" src="%s?s=16" alt="user-avatar" title="username"/> <a href="/%s/%s/commit/%s">%s</a> %s</div> `
2014-03-15 08:50:51 +04:00
)
// ActionDesc accepts int that represents action operation type
// and returns the description.
2014-03-16 20:07:35 +04:00
func ActionDesc ( act Actioner , avatarLink string ) string {
2014-03-15 08:50:51 +04:00
actUserName := act . GetActUserName ( )
repoName := act . GetRepoName ( )
2014-03-16 19:30:35 +04:00
content := act . GetContent ( )
2014-03-15 08:50:51 +04:00
switch act . GetOpType ( ) {
case 1 : // Create repository.
2014-03-16 19:30:35 +04:00
return fmt . Sprintf ( TPL_CREATE_REPO , actUserName , actUserName , actUserName , repoName , repoName )
case 5 : // Commit repository.
var commits [ ] [ ] string
if err := json . Unmarshal ( [ ] byte ( content ) , & commits ) ; err != nil {
return err . Error ( )
}
2014-03-16 20:07:35 +04:00
buf := bytes . NewBuffer ( [ ] byte ( "\n" ) )
for _ , commit := range commits {
buf . WriteString ( fmt . Sprintf ( TPL_COMMIT_REPO_LI , avatarLink , actUserName , repoName , commit [ 0 ] , commit [ 0 ] [ : 7 ] , commit [ 1 ] ) + "\n" )
}
2014-03-16 19:30:35 +04:00
return fmt . Sprintf ( TPL_COMMIT_REPO , actUserName , actUserName , actUserName , repoName , "master" , "master" , actUserName , repoName , actUserName , repoName ,
2014-03-16 20:07:35 +04:00
buf . String ( ) )
2014-03-15 08:50:51 +04:00
default :
return "invalid type"
}
}