diff --git a/.travis.yml b/.travis.yml index 2f2274c2..71242fea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: go go: - 1.4.2 - - 1.5.1 + - 1.5.2 - release - tip diff --git a/arg/arg.go b/arg/arg.go index 04d13e3d..1580c6bd 100644 --- a/arg/arg.go +++ b/arg/arg.go @@ -1,4 +1,4 @@ -// Package provides methods for working with command-line arguments +// Package arg provides methods for working with command-line arguments package arg // ////////////////////////////////////////////////////////////////////////////////// // @@ -32,6 +32,7 @@ const ( FLOAT = 3 ) +// Error codes const ( ERROR_UNSUPPORTED = 0 ERROR_NO_NAME = 1 @@ -47,16 +48,16 @@ const ( // V basic argument struct type V struct { - Mergeble bool // argument supports arguments value merging - Type int // argument type - Value interface{} // default value - Required bool // argument is required - Max float64 // maximum integer argument value - Min float64 // minimum integer argument value - Alias string // list of aliases - - // Non exported field - set bool + Type int // argument type + Max float64 // maximum integer argument value + Min float64 // minimum integer argument value + Alias string // list of aliases + Mergeble bool // argument supports arguments value merging + Required bool // argument is required + + set bool // Non exported field + + Value interface{} // default value } // Map is map with list of argumens diff --git a/changelog.md b/changelog.md index 25136727..2ff81826 100644 --- a/changelog.md +++ b/changelog.md @@ -1,66 +1,70 @@ -### Changelog +## Changelog -#### r6 +#### v1.2.2 -* [crypto] Small improvements in hash generation -* [csv] Increased code coverage -* [easing] Increased code coverage -* [fmtc] Increased code coverage -* [httputil] Increased code coverage -* [jsonutil] Increased code coverage -* [pid] Increased code coverage -* [req] Increased code coverage -* [req] Increased default timeout to 10 seconds -* [strutil] Increased code coverage -* [timeutil] Increased code coverage +* `[req]` Added flag for marking connection to close -#### r5 +#### v1.2.1 -* [log] Now buffered I/O must be enabled manually -* [log] Auto flushing for bufio +* `[crypto]` Small improvements in hash generation +* `[csv]` Increased code coverage +* `[easing]` Increased code coverage +* `[fmtc]` Increased code coverage +* `[httputil]` Increased code coverage +* `[jsonutil]` Increased code coverage +* `[pid]` Increased code coverage +* `[req]` Increased code coverage +* `[req]` Increased default timeout to 10 seconds +* `[strutil]` Increased code coverage +* `[timeutil]` Increased code coverage -#### r4 +#### v1.2 -* [system] Added json tags for User, Group and SessionInfo structs -* [usage] Info now can use os.Args[0] for info rendering -* [version] Added package for working with version in simver notation +* `[log]` Now buffered I/O must be enabled manually +* `[log]` Auto flushing for bufio -#### r3 +#### v1.1.1 -* [arg] Changed default fail values (int -1 → 0, float -1.0 → 0.0) -* [arg] Increased code coverage -* [arg] Many minor fixes -* [cron] Fixed rare bug -* [cron] Increased code coverage -* [crypto] Increased code coverage -* [easing] Increased code coverage -* [errutil] Increased code coverage -* [fmtc] Increased code coverage -* [fmtutil] Increased code coverage -* [jsonutil] Increased code coverage -* [knf] Fixed bug in Reload method for global config -* [knf] Improved Reload method -* [knf] Increased code coverage -* [log] Increased code coverage -* [mathutil] Increased code coverage -* [pid] Increased code coverage -* [rand] Increased code coverage -* [req] Fixed bug with Accept header -* [req] Increased code coverage -* [sliceutil] Increased code coverage -* [sortutil] Increased code coverage -* [spellcheck] Increased code coverage -* [strutil] Increased code coverage -* [system] Added method system.SetProcName for changing process name -* [timeutil] Fixed bug in PrettyDuration method -* [timeutil] Increased code coverage -* [tmp] Increased code coverage +* `[system]` Added json tags for User, Group and SessionInfo structs +* `[usage]` Info now can use os.Args`[0]` for info rendering +* `[version]` Added package for working with version in simver notation -#### r2 +#### v1.1 -* [system] Fixed bug in fs usage calculation -* [usage] Improved new Info struct creation +* `[arg]` Changed default fail values (int -1 → 0, float -1.0 → 0.0) +* `[arg]` Increased code coverage +* `[arg]` Many minor fixes +* `[cron]` Fixed rare bug +* `[cron]` Increased code coverage +* `[crypto]` Increased code coverage +* `[easing]` Increased code coverage +* `[errutil]` Increased code coverage +* `[fmtc]` Increased code coverage +* `[fmtutil]` Increased code coverage +* `[jsonutil]` Increased code coverage +* `[knf]` Fixed bug in Reload method for global config +* `[knf]` Improved Reload method +* `[knf]` Increased code coverage +* `[log]` Increased code coverage +* `[mathutil]` Increased code coverage +* `[pid]` Increased code coverage +* `[rand]` Increased code coverage +* `[req]` Fixed bug with Accept header +* `[req]` Increased code coverage +* `[sliceutil]` Increased code coverage +* `[sortutil]` Increased code coverage +* `[spellcheck]` Increased code coverage +* `[strutil]` Increased code coverage +* `[system]` Added method system.SetProcName for changing process name +* `[timeutil]` Fixed bug in PrettyDuration method +* `[timeutil]` Increased code coverage +* `[tmp]` Increased code coverage -#### r1 +#### v1.0.1 + +* `[system]` Fixed bug in fs usage calculation +* `[usage]` Improved new Info struct creation + +#### v1 Initial public release diff --git a/cron/cron.go b/cron/cron.go index bc828206..5a2c14ad 100644 --- a/cron/cron.go +++ b/cron/cron.go @@ -1,4 +1,4 @@ -// Package provides methods for working with cron expressions +// Package cron provides methods for working with cron expressions package cron // ////////////////////////////////////////////////////////////////////////////////// // @@ -17,6 +17,7 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // +// Aliases const ( YEARLY = "0 0 1 1 *" ANNUALLY = "0 0 1 1 *" diff --git a/cron/cron_test.go b/cron/cron_test.go index dcf53aaf..3832ff40 100644 --- a/cron/cron_test.go +++ b/cron/cron_test.go @@ -118,6 +118,9 @@ func (s *CronSuite) TestParsing(c *C) { e10, err := Parse("0 12 1 1 Wed") + c.Assert(err, IsNil) + c.Assert(e10, NotNil) + c.Assert( e10.Next(time.Date(2015, 6, 1, 0, 0, 0, 0, time.Local)), Equals, diff --git a/crypto/filehash.go b/crypto/filehash.go index 9ca8e6c0..0915c935 100644 --- a/crypto/filehash.go +++ b/crypto/filehash.go @@ -28,7 +28,7 @@ func FileHash(file string) string { hasher := sha256.New() - _, err = io.Copy(hasher, fd) + io.Copy(hasher, fd) return fmt.Sprintf("%064x", hasher.Sum(nil)) } diff --git a/crypto/passwd.go b/crypto/passwd.go index 72bdb89e..a351ed3d 100644 --- a/crypto/passwd.go +++ b/crypto/passwd.go @@ -1,4 +1,4 @@ -// Package with utils for working with crypto data (passwords, uuids, file hashes) +// Package crypto contains utils for working with crypto data (passwords, uuids, file hashes) package crypto // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/csv/csv.go b/csv/csv.go index 7e128065..452f11f5 100644 --- a/csv/csv.go +++ b/csv/csv.go @@ -1,4 +1,4 @@ -// Package with simple csv parser +// Package csv contains simple csv parser package csv // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/easing/ease.go b/easing/ease.go index ff173b0c..cb231241 100644 --- a/easing/ease.go +++ b/easing/ease.go @@ -1,4 +1,4 @@ -// Package with easing functions +// Package easing contains easing functions package easing // ////////////////////////////////////////////////////////////////////////////////// // @@ -14,7 +14,7 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // -// 2 * Pi +// DoublePi is 2 * Pi const DoublePi = math.Pi * 2 // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/env/env.go b/env/env.go index 00b24e51..b6a47905 100644 --- a/env/env.go +++ b/env/env.go @@ -1,6 +1,6 @@ // +build !windows -// Package provides methods for working with environment variables +// Package env provides methods for working with environment variables package env // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/errutil/errutil.go b/errutil/errutil.go index a823fd8d..89008c71 100644 --- a/errutil/errutil.go +++ b/errutil/errutil.go @@ -1,4 +1,4 @@ -// Package provides methods for working with errors +// Package errutil provides methods for working with errors package errutil // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/fmtc/fmtc.go b/fmtc/fmtc.go index a2b01f19..ae7ddcf9 100644 --- a/fmtc/fmtc.go +++ b/fmtc/fmtc.go @@ -1,4 +1,4 @@ -// Package provides methods similar to fmt for colored output +// Package fmtc provides methods similar to fmt for colored output package fmtc // ////////////////////////////////////////////////////////////////////////////////// // @@ -18,10 +18,9 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // const ( - _CODE_RESET = "\033[0m" - _CODE_CLEAN_LINE = "\033[0K" - _CODE_BACKSPACE = "\b" - _CODE_BELL = "\a" + _CODE_RESET = "\033[0m" + _CODE_BACKSPACE = "\b" + _CODE_BELL = "\a" ) // ////////////////////////////////////////////////////////////////////////////////// // @@ -67,12 +66,9 @@ var codes = map[int]int{ // ////////////////////////////////////////////////////////////////////////////////// // -// Disable colors in output +// DisableColors disable colors in output var DisableColors = false -// Used for TPrintf -var lastTPrintSize int - // ////////////////////////////////////////////////////////////////////////////////// // // Println formats using the default formats for its operands and writes to standard @@ -241,11 +237,12 @@ LOOP: output.WriteString("{") output.WriteString(colorCode) output.WriteString("}") + return true - } else { - output.WriteString(colorCode) } + output.WriteString(colorCode) + return false } diff --git a/fmtutil/fmtutil.go b/fmtutil/fmtutil.go index 795e958d..1c2354a6 100644 --- a/fmtutil/fmtutil.go +++ b/fmtutil/fmtutil.go @@ -1,4 +1,4 @@ -// Package provides methods for output formating +// Package fmtutil provides methods for output formating package fmtutil // ////////////////////////////////////////////////////////////////////////////////// // @@ -25,10 +25,10 @@ const ( _TERA = 1099511627776 ) -// Order separator +// OrderSeparator default order separator var OrderSeparator = "," -// Size separator +// SizeSeparator default size separator var SizeSeparator = "" // ////////////////////////////////////////////////////////////////////////////////// // @@ -80,7 +80,6 @@ func ParseSize(size string) uint64 { var ( mlt uint64 pfx string - err error ) ns := strings.ToLower(strings.Replace(size, " ", "", -1)) diff --git a/fsutil/fs.go b/fsutil/fs.go index 223cc991..337b19ba 100644 --- a/fsutil/fs.go +++ b/fsutil/fs.go @@ -1,6 +1,6 @@ // +build !windows -// Package provides methods for working with files in posix compatible systems +// Package fsutil provides methods for working with files in posix compatible systems package fsutil // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/httputil/httputil.go b/httputil/httputil.go index 710e8d23..3852ff42 100644 --- a/httputil/httputil.go +++ b/httputil/httputil.go @@ -1,4 +1,4 @@ -// Package provides methods for working with http request/responses +// Package httputil provides methods for working with http request/responses package httputil // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/jsonutil/jsonutil.go b/jsonutil/jsonutil.go index e4046b9e..aa423fcf 100644 --- a/jsonutil/jsonutil.go +++ b/jsonutil/jsonutil.go @@ -1,4 +1,4 @@ -// Package provides methods for working with json data +// Package jsonutil provides methods for working with json data package jsonutil // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/knf/knf.go b/knf/knf.go index 2152c13d..16f95129 100644 --- a/knf/knf.go +++ b/knf/knf.go @@ -1,4 +1,4 @@ -// Package provides methods for working with configs in KNF format +// Package knf provides methods for working with configs in KNF format package knf // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/knf/validators.go b/knf/validators.go index 241994f5..2463d769 100644 --- a/knf/validators.go +++ b/knf/validators.go @@ -18,7 +18,7 @@ type PropertyValidator func(config *Config, prop string, value interface{}) erro // ////////////////////////////////////////////////////////////////////////////////// // -// Check if given config property is empty or not +// Empty check if given config property is empty or not var Empty = func(config *Config, prop string, value interface{}) error { if config.GetS(prop) == "" { return fmt.Errorf("Property %s can't be empty", prop) @@ -27,7 +27,7 @@ var Empty = func(config *Config, prop string, value interface{}) error { return nil } -// Check if given config property is less then defined value or not +// Less check if given config property is less then defined value or not var Less = func(config *Config, prop string, value interface{}) error { switch value.(type) { case int, int32, int64, uint, uint32, uint64: @@ -45,7 +45,7 @@ var Less = func(config *Config, prop string, value interface{}) error { return nil } -// Check if given config property is greater then defined value or not +// Greater check if given config property is greater then defined value or not var Greater = func(config *Config, prop string, value interface{}) error { switch value.(type) { case int, int32, int64, uint, uint32, uint64: @@ -65,7 +65,7 @@ var Greater = func(config *Config, prop string, value interface{}) error { return nil } -// Check if given config property is equals then defined value or not +// Equals check if given config property is equals then defined value or not var Equals = func(config *Config, prop string, value interface{}) error { switch value.(type) { case int, int32, int64, uint, uint32, uint64: diff --git a/log/log.go b/log/log.go index 68e2ece0..9a58f9c1 100644 --- a/log/log.go +++ b/log/log.go @@ -1,4 +1,4 @@ -// Package with improved logger +// Package log provides improved logger package log // ////////////////////////////////////////////////////////////////////////////////// // @@ -45,15 +45,16 @@ type Logger struct { PrefixCrit bool // Prefix for critical error messages file string - perms os.FileMode fd *os.File w *bufio.Writer - useBufIO bool level int + perms os.FileMode + useBufIO bool } // ////////////////////////////////////////////////////////////////////////////////// // +// Global is global logger struct var Global = &Logger{ PrefixWarn: true, PrefixError: true, @@ -64,7 +65,7 @@ var Global = &Logger{ // ////////////////////////////////////////////////////////////////////////////////// // -// Map with messages prefixes +// PrefixMap is map with messages prefixes var PrefixMap = map[int]string{ DEBUG: "[DEBUG]", INFO: "[INFO]", diff --git a/log/log_test.go b/log/log_test.go index 944ee8fc..7e9eeb5b 100644 --- a/log/log_test.go +++ b/log/log_test.go @@ -8,13 +8,14 @@ package log // ////////////////////////////////////////////////////////////////////////////////// // import ( - . "gopkg.in/check.v1" "io/ioutil" "os" "strings" "testing" "time" + . "gopkg.in/check.v1" + "github.com/essentialkaos/ek/fsutil" ) diff --git a/mathutil/mathutil.go b/mathutil/mathutil.go index 3b5f0663..d5742c5d 100644 --- a/mathutil/mathutil.go +++ b/mathutil/mathutil.go @@ -1,4 +1,4 @@ -// Package with math utils +// Package mathutil provides some additional math methods package mathutil // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/netutil/netutil.go b/netutil/netutil.go index 8635236d..39511a59 100644 --- a/netutil/netutil.go +++ b/netutil/netutil.go @@ -1,4 +1,4 @@ -// Package with network utils +// Package netutil with network utils package netutil // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/pid/pid.go b/pid/pid.go index 023bb212..2497f8f8 100644 --- a/pid/pid.go +++ b/pid/pid.go @@ -1,4 +1,4 @@ -// Package for working with pid files +// Package pid provides methods for working with pid files package pid // ////////////////////////////////////////////////////////////////////////////////// // @@ -21,7 +21,7 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // -// Path to directory with pid files +// Dir is path to directory with pid files var Dir = "/var/run" // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/rand/rand.go b/rand/rand.go index 1d01d8a7..e4c0c529 100644 --- a/rand/rand.go +++ b/rand/rand.go @@ -1,4 +1,4 @@ -// Package for generating random data +// Package rand provides methods for generating random data package rand // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/readme.md b/readme.md index 240011d7..9775e3eb 100644 --- a/readme.md +++ b/readme.md @@ -44,12 +44,12 @@ go get github.com/essentialkaos/ek * `tmp` - Package provides methods for working with temporary data * `usage` - Package provides methods for rendering info for command-line tools * `version` - Package provides methods for parsing semver version info -* `z7` - Package provides methods for working with 7z archives (p7zip wrapper) ### Projects with EK * [ssllabs-client](https://github.com/essentialkaos/ssllabs_client) - Pretty awesome command-line client for public SSLLabs API * [redis-cli-monitor](https://github.com/essentialkaos/redis-cli-monitor) - Tiny redis client for renamed MONITOR commands +* [shdoc](https://github.com/essentialkaos/shdoc) - Tool for viewing and exporting docs for shell scripts ### Test & Coverage Status diff --git a/req/req.go b/req/req.go index 93cc31e6..1e5dc7b7 100644 --- a/req/req.go +++ b/req/req.go @@ -1,4 +1,4 @@ -// Package for working with http request +// Package req for working with http request package req // ////////////////////////////////////////////////////////////////////////////////// // @@ -61,6 +61,7 @@ type Request struct { BasicAuthPassword string // Basic auth password UserAgent string // User Agent string AutoDiscard bool // Automatically discard all responses with status code != 200 + Close bool // Close indicates whether to close the connection after sending request } // Response struct contains response data and properties @@ -144,6 +145,10 @@ func (r Request) Do() (*Response, error) { req.SetBasicAuth(r.BasicAuthUsername, r.BasicAuthPassword) } + if r.Close { + req.Close = true + } + resp, err := Client.Do(req) if err != nil { @@ -165,31 +170,31 @@ func (r Request) Get() (*Response, error) { return r.Do() } -// Get execute as POST request +// Post execute as POST request func (r Request) Post() (*Response, error) { r.Method = POST return r.Do() } -// Get execute as PUT request +// Put execute as PUT request func (r Request) Put() (*Response, error) { r.Method = PUT return r.Do() } -// Get execute as HEAD request +// Head execute as HEAD request func (r Request) Head() (*Response, error) { r.Method = HEAD return r.Do() } -// Get execute as PATCH request +// Patch execute as PATCH request func (r Request) Patch() (*Response, error) { r.Method = PATCH return r.Do() } -// Get execute as DELETE request +// Delete execute as DELETE request func (r Request) Delete() (*Response, error) { r.Method = DELETE return r.Do() diff --git a/req/req_test.go b/req/req_test.go index 366d67fe..afa725b6 100644 --- a/req/req_test.go +++ b/req/req_test.go @@ -215,6 +215,16 @@ func (s *ReqSuite) TestAccept(c *C) { c.Assert(resp.StatusCode, Equals, 200) } +func (s *ReqSuite) TestClose(c *C) { + getResp, err := Request{ + URL: s.url + _URL_GET, + Close: true, + }.Get() + + c.Assert(err, IsNil) + c.Assert(getResp.StatusCode, Equals, 200) +} + func (s *ReqSuite) TestUserAgent(c *C) { resp, err := Request{ URL: s.url + _URL_USER_AGENT, diff --git a/signal/signal.go b/signal/signal.go index 9be99aeb..ae519bb2 100644 --- a/signal/signal.go +++ b/signal/signal.go @@ -1,6 +1,6 @@ // +build !windows -// Package for handling signals +// Package signal provides methods for handling signals package signal // ////////////////////////////////////////////////////////////////////////////////// // @@ -18,6 +18,7 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // +// Signal codes const ( ABRT = syscall.SIGABRT ALRM = syscall.SIGALRM @@ -62,7 +63,7 @@ type Handlers map[os.Signal]func() func (h Handlers) Track() { c := make(chan os.Signal) - for s, _ := range h { + for s := range h { signal.Notify(c, s) } @@ -83,7 +84,7 @@ func (h Handlers) Track() { func (h Handlers) TrackAsync() { c := make(chan os.Signal) - for s, _ := range h { + for s := range h { signal.Notify(c, s) } diff --git a/sliceutil/sliceutil.go b/sliceutil/sliceutil.go index 52ec2dd7..bd1310fd 100644 --- a/sliceutil/sliceutil.go +++ b/sliceutil/sliceutil.go @@ -1,4 +1,4 @@ -// Package with utils for working with slices +// Package sliceutil provides methods for working with slices package sliceutil // ////////////////////////////////////////////////////////////////////////////////// // @@ -8,9 +8,15 @@ package sliceutil // // // ////////////////////////////////////////////////////////////////////////////////// // +import ( + "errors" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + // StringToInterface convert slice with strings to slice with interface{} func StringToInterface(data []string) []interface{} { - result := []interface{}{} + result := make([]interface{}, 0) for _, r := range data { result = append(result, r) @@ -21,7 +27,7 @@ func StringToInterface(data []string) []interface{} { // IntToInterface convert slice with ints to slice with interface{} func IntToInterface(data []int) []interface{} { - result := []interface{}{} + result := make([]interface{}, 0) for _, r := range data { result = append(result, r) @@ -30,6 +36,28 @@ func IntToInterface(data []int) []interface{} { return result } +// StringToError convert slice with strings to slice with errors +func StringToError(data []string) []error { + result := make([]error, 0) + + for _, e := range data { + result = append(result, errors.New(e)) + } + + return result +} + +// StringToError convert slice with errors to slice with strings +func ErrorToString(data []error) []string { + result := make([]string, 0) + + for _, e := range data { + result = append(result, e.Error()) + } + + return result +} + // Contains check if string slice contains some value func Contains(slice []string, value string) bool { if len(slice) == 0 { @@ -44,3 +72,21 @@ func Contains(slice []string, value string) bool { return false } + +// Exclude return slice without items in second given slice +func Exclude(slice []string, items []string) []string { + var result = make([]string, 0) + +LOOP: + for _, i := range slice { + for _, j := range items { + if i == j { + continue LOOP + } + } + + result = append(result, i) + } + + return result +} diff --git a/sliceutil/sliceutil_test.go b/sliceutil/sliceutil_test.go index cc15c77c..3c8677eb 100644 --- a/sliceutil/sliceutil_test.go +++ b/sliceutil/sliceutil_test.go @@ -8,8 +8,10 @@ package sliceutil // ////////////////////////////////////////////////////////////////////////////////// // import ( - . "gopkg.in/check.v1" + "errors" "testing" + + . "gopkg.in/check.v1" ) // ////////////////////////////////////////////////////////////////////////////////// // @@ -38,6 +40,30 @@ func (s *SliceSuite) TestInt2Interface(c *C) { c.Assert(result, DeepEquals, []interface{}{1, 2, 3}) } +func (s *SliceSuite) TestString2Error(c *C) { + source := []string{"A", "B", "C"} + result := StringToError(source) + + c.Assert(result, DeepEquals, + []error{ + errors.New("A"), + errors.New("B"), + errors.New("C"), + }) +} + +func (s *SliceSuite) TestError2String(c *C) { + source := []error{ + errors.New("A"), + errors.New("B"), + errors.New("C"), + } + + result := ErrorToString(source) + + c.Assert(result, DeepEquals, []string{"A", "B", "C"}) +} + func (s *SliceSuite) TestContains(c *C) { source := []string{"1", "2", "3"} @@ -45,3 +71,11 @@ func (s *SliceSuite) TestContains(c *C) { c.Assert(Contains(source, "4"), Equals, false) c.Assert(Contains([]string{}, "1"), Equals, false) } + +func (s *SliceSuite) TestExclude(c *C) { + source := []string{"1", "2", "3", "4", "5", "6"} + + c.Assert(Exclude(source, []string{"1"}), DeepEquals, []string{"2", "3", "4", "5", "6"}) + c.Assert(Exclude(source, []string{"1", "3", "6"}), DeepEquals, []string{"2", "4", "5"}) + c.Assert(Exclude(source, []string{"1", "2", "3", "4", "5", "6"}), DeepEquals, []string{}) +} diff --git a/sortutil/sortutil.go b/sortutil/sortutil.go index 988d1ff8..2057d9f6 100644 --- a/sortutil/sortutil.go +++ b/sortutil/sortutil.go @@ -1,4 +1,4 @@ -// Package with utils for sorting slices +// Package sortutil provides methods for sorting slices package sortutil // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/spellcheck/spellcheck.go b/spellcheck/spellcheck.go index b9a05ac6..e979ba2c 100644 --- a/spellcheck/spellcheck.go +++ b/spellcheck/spellcheck.go @@ -1,4 +1,4 @@ -// Package provides spellcheck based on Damerau–Levenshtein distance algorithm +// Package spellcheck provides spellcheck based on Damerau–Levenshtein distance algorithm package spellcheck // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/strutil/strutil.go b/strutil/strutil.go index cabf0a1f..67c72010 100644 --- a/strutil/strutil.go +++ b/strutil/strutil.go @@ -1,4 +1,4 @@ -// Package provides utils for working with strings +// Package strutil provides methods for working with strings package strutil // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/system/info.go b/system/info.go index 429a6ad9..3adf1220 100644 --- a/system/info.go +++ b/system/info.go @@ -1,6 +1,6 @@ // +build !windows -// Package provides methods for working with system data (metrics/users) +// Package system provides methods for working with system data (metrics/users) package system // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/system/setprocname.go b/system/setprocname.go index 646e5973..946e9c10 100644 --- a/system/setprocname.go +++ b/system/setprocname.go @@ -1,4 +1,5 @@ // +build linux, darwin + package system // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/system/setprocname_windows.go b/system/setprocname_windows.go index d822700f..fa2a820a 100644 --- a/system/setprocname_windows.go +++ b/system/setprocname_windows.go @@ -1,4 +1,5 @@ // +build windows + package system // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/terminal/terminal.go b/terminal/terminal.go index 66d3fba1..c64526b7 100644 --- a/terminal/terminal.go +++ b/terminal/terminal.go @@ -1,6 +1,6 @@ // +build linux, darwin, !windows -// Package provides methods for working with user input +// Package terminal provides methods for working with user input package terminal // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/timeutil/timeutil.go b/timeutil/timeutil.go index 14bd3346..1573d3e5 100644 --- a/timeutil/timeutil.go +++ b/timeutil/timeutil.go @@ -1,4 +1,4 @@ -// Package with time utils +// Package timeutil with time utils package timeutil // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/timeutil/tinydate.go b/timeutil/tinydate.go index 5a006bc7..44c73316 100644 --- a/timeutil/tinydate.go +++ b/timeutil/tinydate.go @@ -18,6 +18,7 @@ type Date uint32 // ////////////////////////////////////////////////////////////////////////////////// // +// StartDate contains start date timestamp var StartDate uint32 = 1322611200 // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/tmp/tmp.go b/tmp/tmp.go index 37d92238..29d3d8ff 100644 --- a/tmp/tmp.go +++ b/tmp/tmp.go @@ -1,4 +1,4 @@ -// Package provides methods for working with temporary data +// Package tmp provides methods and structs for working with temporary data package tmp // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/usage/usage.go b/usage/usage.go index 3d83a519..3ae2f81c 100644 --- a/usage/usage.go +++ b/usage/usage.go @@ -1,4 +1,4 @@ -// Package provides methods for rendering info for command-line tools +// Package usage provides methods and structs for rendering info for command-line tools package usage // ////////////////////////////////////////////////////////////////////////////////// // diff --git a/version/version.go b/version/version.go index 7b64a55e..66febf08 100644 --- a/version/version.go +++ b/version/version.go @@ -1,4 +1,4 @@ -// Package provides methods for parsing semver version info +// Package version provides methods for parsing semver version info package version // ////////////////////////////////////////////////////////////////////////////////// // @@ -9,12 +9,14 @@ package version // ////////////////////////////////////////////////////////////////////////////////// // import ( + "regexp" "strconv" "strings" ) // ////////////////////////////////////////////////////////////////////////////////// // +// Version contains version data type Version struct { raw string versionSlice []int @@ -24,36 +26,41 @@ type Version struct { // ////////////////////////////////////////////////////////////////////////////////// // -func Parse(ver string) *Version { - if ver == "" { +var preRegExp = regexp.MustCompile(`([a-zA-Z-.]{1,})([0-9]{0,})`) + +// ////////////////////////////////////////////////////////////////////////////////// // + +// Parse parse version string and return version struct +func Parse(v string) *Version { + if v == "" { return &Version{} } - result := &Version{raw: ver} + result := &Version{raw: v} - if strings.Contains(ver, "+") { - bs := strings.Split(ver, "+") + if strings.Contains(v, "+") { + bs := strings.Split(v, "+") if bs[1] == "" { - ver = bs[0] + v = bs[0] } else { - ver = bs[0] + v = bs[0] result.build = bs[1] } } - if strings.Contains(ver, "-") { - ps := strings.Split(ver, "-") + if strings.Contains(v, "-") { + ps := strings.Split(v, "-") if ps[1] == "" { - ver = ps[0] + v = ps[0] } else { - ver = ps[0] + v = ps[0] result.preRelease = ps[1] } } - for _, version := range strings.Split(ver, ".") { + for _, version := range strings.Split(v, ".") { iv, err := strconv.Atoi(version) if err != nil { @@ -121,6 +128,111 @@ func (v *Version) Build() string { return v.build } +// Equal return true if version are equal to given +func (v *Version) Equal(version *Version) bool { + if v.Major() != version.Major() { + return false + } + + if v.Minor() != version.Minor() { + return false + } + + if v.Patch() != version.Patch() { + return false + } + + if v.PreRelease() != version.PreRelease() { + return false + } + + if v.Build() != version.Build() { + return false + } + + return true +} + +// Less return true if given version is greater +func (v *Version) Less(version *Version) bool { + if v.Major() < version.Major() { + return true + } + + if v.Minor() < version.Minor() { + return true + } + + if v.Patch() < version.Patch() { + return true + } + + pr1, pr2 := v.PreRelease(), version.PreRelease() + + if pr1 != pr2 { + return prereleaseLess(pr1, pr2) + } + + return false +} + +// Greater return true if given version is less +func (v *Version) Greater(version *Version) bool { + if v.Major() > version.Major() { + return true + } + + if v.Minor() > version.Minor() { + return true + } + + if v.Patch() > version.Patch() { + return true + } + + pr1, pr2 := v.PreRelease(), version.PreRelease() + + if pr1 != pr2 { + return !prereleaseLess(pr1, pr2) + } + + return false +} + +// Contains check is current version contains given version +func (v *Version) Contains(version *Version) bool { + if v.Major() != version.Major() { + return false + } + + if len(v.versionSlice) == 1 { + return true + } + + if v.Minor() != version.Minor() { + return false + } + + if len(v.versionSlice) == 2 { + return true + } + + if v.Patch() != version.Patch() { + return false + } + + return false +} + +// Valid return true if version struct is valid +func (v *Version) Valid() bool { + if v == nil { + return false + } + + return len(v.versionSlice) != 0 +} + // String return version as string func (v *Version) String() string { if v == nil { @@ -129,3 +241,40 @@ func (v *Version) String() string { return v.raw } + +// ////////////////////////////////////////////////////////////////////////////////// // + +// prereleaseLess +func prereleaseLess(pr1, pr2 string) bool { + // Current version is release and given is prerelease + if pr1 == "" && pr2 != "" { + return false + } + + // Current version is prerelease and given is release + if pr1 != "" && pr2 == "" { + return true + } + + // Parse prerelease + pr1Re := preRegExp.FindStringSubmatch(pr1) + pr2Re := preRegExp.FindStringSubmatch(pr2) + + pr1Name := pr1Re[1] + pr2Name := pr2Re[1] + + if pr1Name > pr2Name { + return false + } + + if pr1Name < pr2Name { + return true + } + + // Errors not important, because if subver is empty + // Atoi return 0 + pr1Ver, _ := strconv.Atoi(pr1Re[2]) + pr2Ver, _ := strconv.Atoi(pr2Re[2]) + + return pr1Ver < pr2Ver +} diff --git a/version/version_test.go b/version/version_test.go index 9954a3d6..94c055fd 100644 --- a/version/version_test.go +++ b/version/version_test.go @@ -78,6 +78,22 @@ func (s *VersionSuite) TestString(c *C) { c.Assert(Parse("6.12.1-beta2+exp.sha.5114f85").String(), Equals, "6.12.1-beta2+exp.sha.5114f85") } +func (s *VersionSuite) TestValidation(c *C) { + var v1 *Version + var v2 = &Version{} + + c.Assert(v1.Valid(), Equals, false) + c.Assert(v2.Valid(), Equals, false) + c.Assert(Parse("A").Valid(), Equals, false) + c.Assert(Parse("").Valid(), Equals, false) + + c.Assert(Parse("1").Valid(), Equals, true) + c.Assert(Parse("2.1").Valid(), Equals, true) + c.Assert(Parse("3.4.5").Valid(), Equals, true) + c.Assert(Parse("5-beta1+sha:5114f85").Valid(), Equals, true) + c.Assert(Parse("6.12.1-beta2+exp.sha.5114f85").Valid(), Equals, true) +} + func (s *VersionSuite) TestErrors(c *C) { var v1 *Version var v2 = &Version{} @@ -108,3 +124,52 @@ func (s *VersionSuite) TestErrors(c *C) { c.Assert(v2.Build(), Equals, "") c.Assert(v2.String(), Equals, "") } + +func (s *VersionSuite) TestComparison(c *C) { + c.Assert(Parse("1").Equal(Parse("1")), Equals, true) + c.Assert(Parse("1").Equal(Parse("2")), Equals, false) + c.Assert(Parse("1").Equal(Parse("1.0")), Equals, true) + c.Assert(Parse("1").Equal(Parse("1.1")), Equals, false) + c.Assert(Parse("1").Equal(Parse("1.0.0")), Equals, true) + c.Assert(Parse("1").Equal(Parse("1.0.1")), Equals, false) + c.Assert(Parse("1").Equal(Parse("1.0.0-alpha1")), Equals, false) + c.Assert(Parse("1").Equal(Parse("1.0.0+sha:5114f85")), Equals, false) + c.Assert(Parse("1.0.0+sha:5114f85").Equal(Parse("1.0.0+sha:5114f85")), Equals, true) + + c.Assert(Parse("1").Less(Parse("1")), Equals, false) + c.Assert(Parse("1").Less(Parse("1.0")), Equals, false) + c.Assert(Parse("1").Less(Parse("1.0.0")), Equals, false) + c.Assert(Parse("1").Less(Parse("2")), Equals, true) + c.Assert(Parse("1").Less(Parse("1.1")), Equals, true) + c.Assert(Parse("1").Less(Parse("1.0.1")), Equals, true) + c.Assert(Parse("1.0.1-alpha").Less(Parse("1.0.1")), Equals, true) + c.Assert(Parse("1.0.1").Less(Parse("1.0.1-alpha")), Equals, false) + c.Assert(Parse("1.0.1-alpha").Less(Parse("1.0.1-beta")), Equals, true) + c.Assert(Parse("1.0.1-gamma").Less(Parse("1.0.1-beta")), Equals, false) + c.Assert(Parse("1.0.1-alpha").Less(Parse("1.0.1-alpha1")), Equals, true) + c.Assert(Parse("1.0.1-a4").Less(Parse("1.0.1-a5")), Equals, true) + c.Assert(Parse("1.0.1-a5").Less(Parse("1.0.1-a5")), Equals, false) + + c.Assert(Parse("1").Greater(Parse("1")), Equals, false) + c.Assert(Parse("1").Greater(Parse("1.0")), Equals, false) + c.Assert(Parse("1").Greater(Parse("1.0.0")), Equals, false) + c.Assert(Parse("2").Greater(Parse("1")), Equals, true) + c.Assert(Parse("1.1").Greater(Parse("1")), Equals, true) + c.Assert(Parse("1.0.1").Greater(Parse("1")), Equals, true) + c.Assert(Parse("1.0.1-alpha").Greater(Parse("1.0.1")), Equals, false) + c.Assert(Parse("1.0.1").Greater(Parse("1.0.1-alpha")), Equals, true) + c.Assert(Parse("1.0.1-alpha").Greater(Parse("1.0.1-beta")), Equals, false) + c.Assert(Parse("1.0.1-gamma").Greater(Parse("1.0.1-beta")), Equals, true) + c.Assert(Parse("1.0.1-alpha").Greater(Parse("1.0.1-alpha1")), Equals, false) + c.Assert(Parse("1.0.1-a4").Greater(Parse("1.0.1-a5")), Equals, false) + c.Assert(Parse("1.0.1-a5").Greater(Parse("1.0.1-a5")), Equals, false) + + c.Assert(Parse("1").Contains(Parse("1")), Equals, true) + c.Assert(Parse("1").Contains(Parse("1.1")), Equals, true) + c.Assert(Parse("1").Contains(Parse("1.0.1")), Equals, true) + c.Assert(Parse("2").Contains(Parse("1")), Equals, false) + c.Assert(Parse("1.1").Contains(Parse("1.2")), Equals, false) + c.Assert(Parse("1.0").Contains(Parse("1.0.2")), Equals, true) + c.Assert(Parse("1.0.1").Contains(Parse("1.0.2")), Equals, false) + c.Assert(Parse("1.0.1").Contains(Parse("1.0.1-alpha")), Equals, false) +} diff --git a/z7/z7.go b/z7/z7.go deleted file mode 100644 index e603f4e7..00000000 --- a/z7/z7.go +++ /dev/null @@ -1,453 +0,0 @@ -// Package provides methods for working with 7z archives (p7zip wrapper) -package z7 - -// ////////////////////////////////////////////////////////////////////////////////// // -// // -// Copyright (c) 2009-2015 Essential Kaos // -// Essential Kaos Open Source License // -// // -// ////////////////////////////////////////////////////////////////////////////////// // - -import ( - "errors" - "os" - "os/exec" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/essentialkaos/ek/fsutil" - "github.com/essentialkaos/ek/mathutil" -) - -// ////////////////////////////////////////////////////////////////////////////////// // - -const _BINARY = "7za" - -const ( - _COMPRESSION_MIN = 0 - _COMPRESSION_MAX = 9 - _COMPRESSION_DEFAULT = 4 -) - -const ( - _COMMAND_ADD = "a" - _COMMAND_BENCHMARK = "b" - _COMMAND_DELETE = "d" - _COMMAND_LIST = "l" - _COMMAND_TEST = "t" - _COMMAND_UPDATE = "u" - _COMMAND_EXTRACT = "x" -) - -const ( - _TYPE_7Z = "7z" - _TYPE_ZIP = "zip" - _TYPE_GZIP = "gzip" - _TYPE_XZ = "xz" - _TYPE_BZIP = "bzip2" -) - -const _TEST_OK_VALUE = "Everything is Ok" - -// Props contains properties for packing/unpacking data -type Props struct { - Dir string - File string - FileList string - Exclude string - ExcludeFile string - Compression int - Output string - Password string - Threads int - EncryptHeaders bool - Recurse bool - WorkingDir string -} - -// Info contains info about archive -type Info struct { - Path string - Type string - Method []string - Solid bool - Blocks int - PhysicalSize int - HeadersSize int - Files []*FileInfo -} - -// FileInfo contains info about file inside archive -type FileInfo struct { - Path string - Folder string - Size int - PackedSize int - Modified time.Time - Created time.Time - Accessed time.Time - Attributes string - CRC int - Encrypted bool - Method []string - Block int - Comment string - HostOS string - Version int -} - -// ////////////////////////////////////////////////////////////////////////////////// // - -// Add add files to archive -func Add(arch interface{}, files ...string) (string, error) { - return AddList(arch, files) -} - -// AddList add files as string slice -func AddList(arch interface{}, files ...[]string) (string, error) { - props, err := procProps(arch) - - if err != nil { - return "", err - } - - var ( - cwd string - file string - ) - - file, _ = filepath.Abs(props.File) - - if props.Dir != "" { - cwd, _ = os.Getwd() - os.Chdir(props.Dir) - } - - args := propsToArgs(props, _COMMAND_ADD) - - if len(files) != 0 { - args = append(args, files[0]...) - } - - out, err := execBinary(file, _COMMAND_ADD, args) - - if props.Dir != "" { - os.Chdir(cwd) - } - - return out, err -} - -// Extract extract arhive -func Extract(arch interface{}) (string, error) { - props, err := procProps(arch) - - if err != nil { - return "", err - } - - if !fsutil.IsExist(props.File) { - return "", errors.New("File " + props.File + " is not exist") - } - - if !fsutil.IsReadable(props.File) { - return "", errors.New("File " + props.File + " is not readable") - } - - if props.Output != "" && !fsutil.IsWritable(props.Output) { - return "", errors.New("Directory " + props.Output + " is not writable") - } - - var ( - cwd string - file string - ) - - file, _ = filepath.Abs(props.File) - - if props.Dir != "" { - cwd, _ = os.Getwd() - os.Chdir(props.Dir) - } - - args := propsToArgs(props, _COMMAND_EXTRACT) - out, err := execBinary(file, _COMMAND_EXTRACT, args) - - if props.Dir != "" { - os.Chdir(cwd) - } - - return out, err -} - -// List return info about archive -func List(arch interface{}) (*Info, error) { - props, err := procProps(arch) - - if err != nil { - return &Info{}, err - } - - if !fsutil.IsExist(props.File) { - return nil, errors.New("File " + props.File + " is not exist") - } - - if !fsutil.IsReadable(props.File) { - return nil, errors.New("File " + props.File + " is not readable") - } - - args := propsToArgs(props, _COMMAND_LIST) - out, err := execBinary(props.File, _COMMAND_LIST, args) - - if err != nil { - return nil, errors.New(out) - } - - return parseInfoString(out), nil -} - -// Test test archive -func Test(arch interface{}) (string, bool) { - props, err := procProps(arch) - - if err != nil { - return "", false - } - - if !fsutil.IsExist(props.File) { - return "", false - } - - if !fsutil.IsReadable(props.File) { - return "", false - } - - args := propsToArgs(props, _COMMAND_TEST) - out, err := execBinary(props.File, _COMMAND_TEST, args) - - for _, line := range strings.Split(out, "\n") { - if line == _TEST_OK_VALUE { - return out, true - } - } - - return out, false -} - -// Delete remove files from archive -func Delete(arch interface{}, files ...string) (string, error) { - return DeleteList(arch, files) -} - -// DeleteList remove files provided as string slice from archive -func DeleteList(arch interface{}, files ...[]string) (string, error) { - props, err := procProps(arch) - - if err != nil { - return "", err - } - - args := propsToArgs(props, _COMMAND_DELETE) - - if len(files) != 0 { - args = append(args, files[0]...) - } - - out, err := execBinary(props.File, _COMMAND_DELETE, args) - - return out, err -} - -// ////////////////////////////////////////////////////////////////////////////////// // - -func execBinary(arch string, command string, args []string) (string, error) { - var cmd = exec.Command(_BINARY) - - cmd.Args = append(cmd.Args, command) - cmd.Args = append(cmd.Args, arch) - cmd.Args = append(cmd.Args, args...) - - out, err := cmd.Output() - - return string(out[:]), err -} - -func procProps(p interface{}) (*Props, error) { - switch p.(type) { - case *Props: - return p.(*Props), nil - case string: - return &Props{File: p.(string), Compression: _COMPRESSION_DEFAULT}, nil - default: - return nil, errors.New("Unknown properties type") - } -} - -func propsToArgs(props *Props, command string) []string { - var args = []string{"", "-y"} - - if command == _COMMAND_ADD { - compLvl := strconv.Itoa(mathutil.Between(props.Compression, _COMPRESSION_MIN, _COMPRESSION_MAX)) - - args = append(args, "-mx="+compLvl) - - switch { - case props.Threads == -1: - args = append(args, "-mt=off") - case props.Threads > 0: - args = append(args, "-mt="+strconv.Itoa(mathutil.Between(props.Threads, 1, 128))) - } - - if props.EncryptHeaders { - args = append(args, "-mhe") - } - - if props.Exclude != "" { - args = append(args, "-x"+props.Exclude) - } else if props.ExcludeFile != "" { - args = append(args, "-x@"+props.ExcludeFile) - } - - if props.FileList != "" { - args = append(args, "-i@"+props.FileList) - } - - } else if command == _COMMAND_EXTRACT { - if props.Output != "" { - args = append(args, "-o"+props.Output) - } - } else if command == _COMMAND_LIST { - args = append(args, "-slt") - } - - if props.Password != "" { - args = append(args, "-p"+props.Password) - } - - if props.Recurse { - args = append(args, "-r") - } - - if props.WorkingDir != "" { - args = append(args, "-w"+props.WorkingDir) - } - - return args -} - -func parseInfoString(infoData string) *Info { - var data = strings.Split(infoData, "\n") - var info = &Info{} - - var fStart, fCount, fRecs int - var rList map[string]string - - info.Path = getValue(data[7]) - info.Type = getValue(data[8]) - - if info.Type == _TYPE_7Z { - fStart = 16 - fRecs = 10 - - rList = parseRecordList(data[7:15]) - - info.Method = strings.Split(rList["Method"], " ") - info.Solid = rList["Solid"] == "+" - - info.Blocks, _ = strconv.Atoi(rList["Blocks"]) - info.PhysicalSize, _ = strconv.Atoi(rList["Physical Size"]) - info.HeadersSize, _ = strconv.Atoi(rList["Headers Size"]) - } else if info.Type == _TYPE_ZIP { - fStart = 12 - fRecs = 14 - - rList = parseRecordList(data[7:11]) - - info.PhysicalSize, _ = strconv.Atoi(rList["Physical Size"]) - } else if info.Type == _TYPE_GZIP { - fStart = 11 - fRecs = 7 - } else if info.Type == _TYPE_XZ { - fStart = 12 - fRecs = 4 - - rList = parseRecordList(data[7:11]) - - info.Method = strings.Split(rList["Method"], " ") - } else if info.Type == _TYPE_BZIP { - fStart = 11 - fRecs = 2 - } else { - return info - } - - fCount = (len(data) - fStart - 1) / fRecs - - for i := 0; i < fCount; i++ { - start := (i * fRecs) + fStart - end := start + fRecs - - info.Files = append(info.Files, parseFileInfoString(data[start:end])) - } - - return info -} - -func parseFileInfoString(data []string) *FileInfo { - var info = &FileInfo{} - var rList = parseRecordList(data) - - crc, _ := strconv.ParseInt(rList["CRC"], 16, 0) - - info.Path = rList["Path"] - info.Folder = rList["Folder"] - info.Size, _ = strconv.Atoi(rList["Size"]) - info.PackedSize, _ = strconv.Atoi(rList["Packed Size"]) - info.Modified = parseDateString(rList["Modified"]) - info.Created = parseDateString(rList["Created"]) - info.Accessed = parseDateString(rList["Accessed"]) - info.Attributes = rList["Attributes"] - info.CRC = int(crc) - info.Comment = rList["Comment"] - info.Encrypted = rList["Encrypted"] == "+" - info.Method = strings.Split(rList["Method"], " ") - info.Block, _ = strconv.Atoi(rList["Block"]) - info.HostOS = rList["Host OS"] - info.Version, _ = strconv.Atoi(rList["Version"]) - - return info -} - -func parseRecordList(data []string) map[string]string { - var result = make(map[string]string) - - for _, rec := range data { - if rec != "" { - revVal := strings.Split(rec, " = ") - result[revVal[0]] = revVal[1] - } - } - - return result -} - -func parseDateString(data string) time.Time { - if data == "" { - return time.Time{} - } - - year, _ := strconv.Atoi(data[0:4]) - month, _ := strconv.Atoi(data[5:7]) - day, _ := strconv.Atoi(data[8:10]) - hour, _ := strconv.Atoi(data[11:13]) - min, _ := strconv.Atoi(data[14:16]) - sec, _ := strconv.Atoi(data[17:19]) - - return time.Date(year, time.Month(month), day, hour, min, sec, 0, time.UTC) -} - -func getValue(s string) string { - return strings.Split(s, " = ")[1] -}