diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2019-07-16 08:13:03 +0800 |
---|---|---|
committer | techknowlogick <techknowlogick@gitea.io> | 2019-07-15 20:13:03 -0400 |
commit | d2958d9f4633ddbde2202952d665b3d562eb0415 (patch) | |
tree | 59f6d1c0ed6c886ba0caa6d96d5a175debf376b7 /vendor/github.com | |
parent | 760c47389696e97131a3d13629a0a5a4576e5283 (diff) | |
download | gitea-d2958d9f4633ddbde2202952d665b3d562eb0415.tar.gz gitea-d2958d9f4633ddbde2202952d665b3d562eb0415.zip |
Move status table to cron package (#7370)
Diffstat (limited to 'vendor/github.com')
-rw-r--r-- | vendor/github.com/gogits/cron/parser.go | 234 | ||||
-rw-r--r-- | vendor/github.com/gogs/cron/.gitignore (renamed from vendor/github.com/gogits/cron/.gitignore) | 0 | ||||
-rw-r--r-- | vendor/github.com/gogs/cron/.travis.yml (renamed from vendor/github.com/gogits/cron/.travis.yml) | 0 | ||||
-rw-r--r-- | vendor/github.com/gogs/cron/LICENSE (renamed from vendor/github.com/gogits/cron/LICENSE) | 0 | ||||
-rw-r--r-- | vendor/github.com/gogs/cron/README.md (renamed from vendor/github.com/gogits/cron/README.md) | 0 | ||||
-rw-r--r-- | vendor/github.com/gogs/cron/constantdelay.go (renamed from vendor/github.com/gogits/cron/constantdelay.go) | 0 | ||||
-rw-r--r-- | vendor/github.com/gogs/cron/cron.go (renamed from vendor/github.com/gogits/cron/cron.go) | 92 | ||||
-rw-r--r-- | vendor/github.com/gogs/cron/doc.go (renamed from vendor/github.com/gogits/cron/doc.go) | 8 | ||||
-rw-r--r-- | vendor/github.com/gogs/cron/parser.go | 380 | ||||
-rw-r--r-- | vendor/github.com/gogs/cron/spec.go (renamed from vendor/github.com/gogits/cron/spec.go) | 1 |
10 files changed, 443 insertions, 272 deletions
diff --git a/vendor/github.com/gogits/cron/parser.go b/vendor/github.com/gogits/cron/parser.go deleted file mode 100644 index fd217c92db..0000000000 --- a/vendor/github.com/gogits/cron/parser.go +++ /dev/null @@ -1,234 +0,0 @@ -package cron - -import ( - "fmt" - "log" - "math" - "strconv" - "strings" - "time" -) - -// Parse returns a new crontab schedule representing the given spec. -// It returns a descriptive error if the spec is not valid. -// -// It accepts -// - Full crontab specs, e.g. "* * * * * ?" -// - Descriptors, e.g. "@midnight", "@every 1h30m" -func Parse(spec string) (_ Schedule, err error) { - // Convert panics into errors - defer func() { - if recovered := recover(); recovered != nil { - err = fmt.Errorf("%v", recovered) - } - }() - - if spec[0] == '@' { - return parseDescriptor(spec), nil - } - - // Split on whitespace. We require 5 or 6 fields. - // (second) (minute) (hour) (day of month) (month) (day of week, optional) - fields := strings.Fields(spec) - if len(fields) != 5 && len(fields) != 6 { - log.Panicf("Expected 5 or 6 fields, found %d: %s", len(fields), spec) - } - - // If a sixth field is not provided (DayOfWeek), then it is equivalent to star. - if len(fields) == 5 { - fields = append(fields, "*") - } - - schedule := &SpecSchedule{ - Second: getField(fields[0], seconds), - Minute: getField(fields[1], minutes), - Hour: getField(fields[2], hours), - Dom: getField(fields[3], dom), - Month: getField(fields[4], months), - Dow: getField(fields[5], dow), - } - - return schedule, nil -} - -// getField returns an Int with the bits set representing all of the times that -// the field represents. A "field" is a comma-separated list of "ranges". -func getField(field string, r bounds) uint64 { - // list = range {"," range} - var bits uint64 - ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' }) - for _, expr := range ranges { - bits |= getRange(expr, r) - } - return bits -} - -// getRange returns the bits indicated by the given expression: -// number | number "-" number [ "/" number ] -func getRange(expr string, r bounds) uint64 { - - var ( - start, end, step uint - rangeAndStep = strings.Split(expr, "/") - lowAndHigh = strings.Split(rangeAndStep[0], "-") - singleDigit = len(lowAndHigh) == 1 - ) - - var extra_star uint64 - if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" { - start = r.min - end = r.max - extra_star = starBit - } else { - start = parseIntOrName(lowAndHigh[0], r.names) - switch len(lowAndHigh) { - case 1: - end = start - case 2: - end = parseIntOrName(lowAndHigh[1], r.names) - default: - log.Panicf("Too many hyphens: %s", expr) - } - } - - switch len(rangeAndStep) { - case 1: - step = 1 - case 2: - step = mustParseInt(rangeAndStep[1]) - - // Special handling: "N/step" means "N-max/step". - if singleDigit { - end = r.max - } - default: - log.Panicf("Too many slashes: %s", expr) - } - - if start < r.min { - log.Panicf("Beginning of range (%d) below minimum (%d): %s", start, r.min, expr) - } - if end > r.max { - log.Panicf("End of range (%d) above maximum (%d): %s", end, r.max, expr) - } - if start > end { - log.Panicf("Beginning of range (%d) beyond end of range (%d): %s", start, end, expr) - } - if step == 0 { - log.Panicf("Step of range should be a positive number: %s", expr) - } - - return getBits(start, end, step) | extra_star -} - -// parseIntOrName returns the (possibly-named) integer contained in expr. -func parseIntOrName(expr string, names map[string]uint) uint { - if names != nil { - if namedInt, ok := names[strings.ToLower(expr)]; ok { - return namedInt - } - } - return mustParseInt(expr) -} - -// mustParseInt parses the given expression as an int or panics. -func mustParseInt(expr string) uint { - num, err := strconv.Atoi(expr) - if err != nil { - log.Panicf("Failed to parse int from %s: %s", expr, err) - } - if num < 0 { - log.Panicf("Negative number (%d) not allowed: %s", num, expr) - } - - return uint(num) -} - -// getBits sets all bits in the range [min, max], modulo the given step size. -func getBits(min, max, step uint) uint64 { - var bits uint64 - - // If step is 1, use shifts. - if step == 1 { - return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min) - } - - // Else, use a simple loop. - for i := min; i <= max; i += step { - bits |= 1 << i - } - return bits -} - -// all returns all bits within the given bounds. (plus the star bit) -func all(r bounds) uint64 { - return getBits(r.min, r.max, 1) | starBit -} - -// parseDescriptor returns a pre-defined schedule for the expression, or panics -// if none matches. -func parseDescriptor(spec string) Schedule { - switch spec { - case "@yearly", "@annually": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: 1 << hours.min, - Dom: 1 << dom.min, - Month: 1 << months.min, - Dow: all(dow), - } - - case "@monthly": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: 1 << hours.min, - Dom: 1 << dom.min, - Month: all(months), - Dow: all(dow), - } - - case "@weekly": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: 1 << hours.min, - Dom: all(dom), - Month: all(months), - Dow: 1 << dow.min, - } - - case "@daily", "@midnight": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: 1 << hours.min, - Dom: all(dom), - Month: all(months), - Dow: all(dow), - } - - case "@hourly": - return &SpecSchedule{ - Second: 1 << seconds.min, - Minute: 1 << minutes.min, - Hour: all(hours), - Dom: all(dom), - Month: all(months), - Dow: all(dow), - } - } - - const every = "@every " - if strings.HasPrefix(spec, every) { - duration, err := time.ParseDuration(spec[len(every):]) - if err != nil { - log.Panicf("Failed to parse duration %s: %s", spec, err) - } - return Every(duration) - } - - log.Panicf("Unrecognized descriptor: %s", spec) - return nil -} diff --git a/vendor/github.com/gogits/cron/.gitignore b/vendor/github.com/gogs/cron/.gitignore index 00268614f0..00268614f0 100644 --- a/vendor/github.com/gogits/cron/.gitignore +++ b/vendor/github.com/gogs/cron/.gitignore diff --git a/vendor/github.com/gogits/cron/.travis.yml b/vendor/github.com/gogs/cron/.travis.yml index 4f2ee4d973..4f2ee4d973 100644 --- a/vendor/github.com/gogits/cron/.travis.yml +++ b/vendor/github.com/gogs/cron/.travis.yml diff --git a/vendor/github.com/gogits/cron/LICENSE b/vendor/github.com/gogs/cron/LICENSE index 3a0f627ffe..3a0f627ffe 100644 --- a/vendor/github.com/gogits/cron/LICENSE +++ b/vendor/github.com/gogs/cron/LICENSE diff --git a/vendor/github.com/gogits/cron/README.md b/vendor/github.com/gogs/cron/README.md index 157ed082d4..157ed082d4 100644 --- a/vendor/github.com/gogits/cron/README.md +++ b/vendor/github.com/gogs/cron/README.md diff --git a/vendor/github.com/gogits/cron/constantdelay.go b/vendor/github.com/gogs/cron/constantdelay.go index cd6e7b1be9..cd6e7b1be9 100644 --- a/vendor/github.com/gogits/cron/constantdelay.go +++ b/vendor/github.com/gogs/cron/constantdelay.go diff --git a/vendor/github.com/gogits/cron/cron.go b/vendor/github.com/gogs/cron/cron.go index ed6ad21c1b..4da9f4ae6c 100644 --- a/vendor/github.com/gogits/cron/cron.go +++ b/vendor/github.com/gogs/cron/cron.go @@ -1,5 +1,3 @@ -// This library implements a cron spec parser and runner. See the README for -// more details. package cron import ( @@ -19,6 +17,7 @@ type Cron struct { snapshot chan []*Entry running bool ErrorLog *log.Logger + location *time.Location } // Job is an interface for submitted cron jobs. @@ -74,8 +73,13 @@ func (s byTime) Less(i, j int) bool { return s[i].Next.Before(s[j].Next) } -// New returns a new Cron job runner. +// New returns a new Cron job runner, in the Local time zone. func New() *Cron { + return NewWithLocation(time.Now().Location()) +} + +// NewWithLocation returns a new Cron job runner. +func NewWithLocation(location *time.Location) *Cron { return &Cron{ entries: nil, add: make(chan *Entry), @@ -83,6 +87,7 @@ func New() *Cron { snapshot: make(chan []*Entry), running: false, ErrorLog: nil, + location: location, } } @@ -131,6 +136,11 @@ func (c *Cron) Entries() []*Entry { return c.entrySnapshot() } +// Location gets the time zone location +func (c *Cron) Location() *time.Location { + return c.location +} + // Start the cron scheduler in its own go-routine, or no-op if already started. func (c *Cron) Start() { if c.running { @@ -140,6 +150,15 @@ func (c *Cron) Start() { go c.run() } +// Run the cron scheduler, or no-op if already running. +func (c *Cron) Run() { + if c.running { + return + } + c.running = true + c.run() +} + func (c *Cron) runWithRecovery(j Job) { defer func() { if r := recover(); r != nil { @@ -152,11 +171,11 @@ func (c *Cron) runWithRecovery(j Job) { j.Run() } -// Run the scheduler.. this is private just due to the need to synchronize +// Run the scheduler. this is private just due to the need to synchronize // access to the 'running' state variable. func (c *Cron) run() { // Figure out the next activation times for each entry. - now := time.Now().Local() + now := c.now() for _, entry := range c.entries { entry.Next = entry.Schedule.Next(now) } @@ -165,45 +184,47 @@ func (c *Cron) run() { // Determine the next entry to run. sort.Sort(byTime(c.entries)) - var effective time.Time + var timer *time.Timer if len(c.entries) == 0 || c.entries[0].Next.IsZero() { // If there are no entries yet, just sleep - it still handles new entries // and stop requests. - effective = now.AddDate(10, 0, 0) + timer = time.NewTimer(100000 * time.Hour) } else { - effective = c.entries[0].Next + timer = time.NewTimer(c.entries[0].Next.Sub(now)) } - timer := time.NewTimer(effective.Sub(now)) - select { - case now = <-timer.C: - // Run every entry whose next time was this effective time. - for _, e := range c.entries { - if e.Next != effective { - break + for { + select { + case now = <-timer.C: + now = now.In(c.location) + // Run every entry whose next time was less than now + for _, e := range c.entries { + if e.Next.After(now) || e.Next.IsZero() { + break + } + go c.runWithRecovery(e.Job) + e.ExecTimes++ + e.Prev = e.Next + e.Next = e.Schedule.Next(now) } - go c.runWithRecovery(e.Job) - e.ExecTimes++ - e.Prev = e.Next - e.Next = e.Schedule.Next(now) - } - continue - case newEntry := <-c.add: - c.entries = append(c.entries, newEntry) - newEntry.Next = newEntry.Schedule.Next(time.Now().Local()) + case newEntry := <-c.add: + timer.Stop() + now = c.now() + newEntry.Next = newEntry.Schedule.Next(now) + c.entries = append(c.entries, newEntry) - case <-c.snapshot: - c.snapshot <- c.entrySnapshot() + case <-c.snapshot: + c.snapshot <- c.entrySnapshot() + continue - case <-c.stop: - timer.Stop() - return - } + case <-c.stop: + timer.Stop() + return + } - // 'now' should be updated after newEntry and snapshot cases. - now = time.Now().Local() - timer.Stop() + break + } } } @@ -241,3 +262,8 @@ func (c *Cron) entrySnapshot() []*Entry { } return entries } + +// now returns current time in c location +func (c *Cron) now() time.Time { + return time.Now().In(c.location) +} diff --git a/vendor/github.com/gogits/cron/doc.go b/vendor/github.com/gogs/cron/doc.go index dbdf50127a..3700cf655a 100644 --- a/vendor/github.com/gogits/cron/doc.go +++ b/vendor/github.com/gogs/cron/doc.go @@ -84,16 +84,16 @@ You may use one of several pre-defined schedules in place of a cron expression. Intervals -You may also schedule a job to execute at fixed intervals. This is supported by -formatting the cron spec like this: +You may also schedule a job to execute at fixed intervals, starting at the time it's added +or cron is run. This is supported by formatting the cron spec like this: @every <duration> where "duration" is a string accepted by time.ParseDuration (http://golang.org/pkg/time/#ParseDuration). -For example, "@every 1h30m10s" would indicate a schedule that activates every -1 hour, 30 minutes, 10 seconds. +For example, "@every 1h30m10s" would indicate a schedule that activates immediately, +and then every 1 hour, 30 minutes, 10 seconds. Note: The interval does not take the job runtime into account. For example, if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes, diff --git a/vendor/github.com/gogs/cron/parser.go b/vendor/github.com/gogs/cron/parser.go new file mode 100644 index 0000000000..a5e83c0a8d --- /dev/null +++ b/vendor/github.com/gogs/cron/parser.go @@ -0,0 +1,380 @@ +package cron + +import ( + "fmt" + "math" + "strconv" + "strings" + "time" +) + +// Configuration options for creating a parser. Most options specify which +// fields should be included, while others enable features. If a field is not +// included the parser will assume a default value. These options do not change +// the order fields are parse in. +type ParseOption int + +const ( + Second ParseOption = 1 << iota // Seconds field, default 0 + Minute // Minutes field, default 0 + Hour // Hours field, default 0 + Dom // Day of month field, default * + Month // Month field, default * + Dow // Day of week field, default * + DowOptional // Optional day of week field, default * + Descriptor // Allow descriptors such as @monthly, @weekly, etc. +) + +var places = []ParseOption{ + Second, + Minute, + Hour, + Dom, + Month, + Dow, +} + +var defaults = []string{ + "0", + "0", + "0", + "*", + "*", + "*", +} + +// A custom Parser that can be configured. +type Parser struct { + options ParseOption + optionals int +} + +// Creates a custom Parser with custom options. +// +// // Standard parser without descriptors +// specParser := NewParser(Minute | Hour | Dom | Month | Dow) +// sched, err := specParser.Parse("0 0 15 */3 *") +// +// // Same as above, just excludes time fields +// subsParser := NewParser(Dom | Month | Dow) +// sched, err := specParser.Parse("15 */3 *") +// +// // Same as above, just makes Dow optional +// subsParser := NewParser(Dom | Month | DowOptional) +// sched, err := specParser.Parse("15 */3") +// +func NewParser(options ParseOption) Parser { + optionals := 0 + if options&DowOptional > 0 { + options |= Dow + optionals++ + } + return Parser{options, optionals} +} + +// Parse returns a new crontab schedule representing the given spec. +// It returns a descriptive error if the spec is not valid. +// It accepts crontab specs and features configured by NewParser. +func (p Parser) Parse(spec string) (Schedule, error) { + if len(spec) == 0 { + return nil, fmt.Errorf("Empty spec string") + } + if spec[0] == '@' && p.options&Descriptor > 0 { + return parseDescriptor(spec) + } + + // Figure out how many fields we need + max := 0 + for _, place := range places { + if p.options&place > 0 { + max++ + } + } + min := max - p.optionals + + // Split fields on whitespace + fields := strings.Fields(spec) + + // Validate number of fields + if count := len(fields); count < min || count > max { + if min == max { + return nil, fmt.Errorf("Expected exactly %d fields, found %d: %s", min, count, spec) + } + return nil, fmt.Errorf("Expected %d to %d fields, found %d: %s", min, max, count, spec) + } + + // Fill in missing fields + fields = expandFields(fields, p.options) + + var err error + field := func(field string, r bounds) uint64 { + if err != nil { + return 0 + } + var bits uint64 + bits, err = getField(field, r) + return bits + } + + var ( + second = field(fields[0], seconds) + minute = field(fields[1], minutes) + hour = field(fields[2], hours) + dayofmonth = field(fields[3], dom) + month = field(fields[4], months) + dayofweek = field(fields[5], dow) + ) + if err != nil { + return nil, err + } + + return &SpecSchedule{ + Second: second, + Minute: minute, + Hour: hour, + Dom: dayofmonth, + Month: month, + Dow: dayofweek, + }, nil +} + +func expandFields(fields []string, options ParseOption) []string { + n := 0 + count := len(fields) + expFields := make([]string, len(places)) + copy(expFields, defaults) + for i, place := range places { + if options&place > 0 { + expFields[i] = fields[n] + n++ + } + if n == count { + break + } + } + return expFields +} + +var standardParser = NewParser( + Minute | Hour | Dom | Month | Dow | Descriptor, +) + +// ParseStandard returns a new crontab schedule representing the given standardSpec +// (https://en.wikipedia.org/wiki/Cron). It differs from Parse requiring to always +// pass 5 entries representing: minute, hour, day of month, month and day of week, +// in that order. It returns a descriptive error if the spec is not valid. +// +// It accepts +// - Standard crontab specs, e.g. "* * * * ?" +// - Descriptors, e.g. "@midnight", "@every 1h30m" +func ParseStandard(standardSpec string) (Schedule, error) { + return standardParser.Parse(standardSpec) +} + +var defaultParser = NewParser( + Second | Minute | Hour | Dom | Month | DowOptional | Descriptor, +) + +// Parse returns a new crontab schedule representing the given spec. +// It returns a descriptive error if the spec is not valid. +// +// It accepts +// - Full crontab specs, e.g. "* * * * * ?" +// - Descriptors, e.g. "@midnight", "@every 1h30m" +func Parse(spec string) (Schedule, error) { + return defaultParser.Parse(spec) +} + +// getField returns an Int with the bits set representing all of the times that +// the field represents or error parsing field value. A "field" is a comma-separated +// list of "ranges". +func getField(field string, r bounds) (uint64, error) { + var bits uint64 + ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' }) + for _, expr := range ranges { + bit, err := getRange(expr, r) + if err != nil { + return bits, err + } + bits |= bit + } + return bits, nil +} + +// getRange returns the bits indicated by the given expression: +// number | number "-" number [ "/" number ] +// or error parsing range. +func getRange(expr string, r bounds) (uint64, error) { + var ( + start, end, step uint + rangeAndStep = strings.Split(expr, "/") + lowAndHigh = strings.Split(rangeAndStep[0], "-") + singleDigit = len(lowAndHigh) == 1 + err error + ) + + var extra uint64 + if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" { + start = r.min + end = r.max + extra = starBit + } else { + start, err = parseIntOrName(lowAndHigh[0], r.names) + if err != nil { + return 0, err + } + switch len(lowAndHigh) { + case 1: + end = start + case 2: + end, err = parseIntOrName(lowAndHigh[1], r.names) + if err != nil { + return 0, err + } + default: + return 0, fmt.Errorf("Too many hyphens: %s", expr) + } + } + + switch len(rangeAndStep) { + case 1: + step = 1 + case 2: + step, err = mustParseInt(rangeAndStep[1]) + if err != nil { + return 0, err + } + + // Special handling: "N/step" means "N-max/step". + if singleDigit { + end = r.max + } + default: + return 0, fmt.Errorf("Too many slashes: %s", expr) + } + + if start < r.min { + return 0, fmt.Errorf("Beginning of range (%d) below minimum (%d): %s", start, r.min, expr) + } + if end > r.max { + return 0, fmt.Errorf("End of range (%d) above maximum (%d): %s", end, r.max, expr) + } + if start > end { + return 0, fmt.Errorf("Beginning of range (%d) beyond end of range (%d): %s", start, end, expr) + } + if step == 0 { + return 0, fmt.Errorf("Step of range should be a positive number: %s", expr) + } + + return getBits(start, end, step) | extra, nil +} + +// parseIntOrName returns the (possibly-named) integer contained in expr. +func parseIntOrName(expr string, names map[string]uint) (uint, error) { + if names != nil { + if namedInt, ok := names[strings.ToLower(expr)]; ok { + return namedInt, nil + } + } + return mustParseInt(expr) +} + +// mustParseInt parses the given expression as an int or returns an error. +func mustParseInt(expr string) (uint, error) { + num, err := strconv.Atoi(expr) + if err != nil { + return 0, fmt.Errorf("Failed to parse int from %s: %s", expr, err) + } + if num < 0 { + return 0, fmt.Errorf("Negative number (%d) not allowed: %s", num, expr) + } + + return uint(num), nil +} + +// getBits sets all bits in the range [min, max], modulo the given step size. +func getBits(min, max, step uint) uint64 { + var bits uint64 + + // If step is 1, use shifts. + if step == 1 { + return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min) + } + + // Else, use a simple loop. + for i := min; i <= max; i += step { + bits |= 1 << i + } + return bits +} + +// all returns all bits within the given bounds. (plus the star bit) +func all(r bounds) uint64 { + return getBits(r.min, r.max, 1) | starBit +} + +// parseDescriptor returns a predefined schedule for the expression, or error if none matches. +func parseDescriptor(descriptor string) (Schedule, error) { + switch descriptor { + case "@yearly", "@annually": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: 1 << hours.min, + Dom: 1 << dom.min, + Month: 1 << months.min, + Dow: all(dow), + }, nil + + case "@monthly": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: 1 << hours.min, + Dom: 1 << dom.min, + Month: all(months), + Dow: all(dow), + }, nil + + case "@weekly": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: 1 << hours.min, + Dom: all(dom), + Month: all(months), + Dow: 1 << dow.min, + }, nil + + case "@daily", "@midnight": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: 1 << hours.min, + Dom: all(dom), + Month: all(months), + Dow: all(dow), + }, nil + + case "@hourly": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: all(hours), + Dom: all(dom), + Month: all(months), + Dow: all(dow), + }, nil + } + + const every = "@every " + if strings.HasPrefix(descriptor, every) { + duration, err := time.ParseDuration(descriptor[len(every):]) + if err != nil { + return nil, fmt.Errorf("Failed to parse duration %s: %s", descriptor, err) + } + return Every(duration), nil + } + + return nil, fmt.Errorf("Unrecognized descriptor: %s", descriptor) +} diff --git a/vendor/github.com/gogits/cron/spec.go b/vendor/github.com/gogs/cron/spec.go index 2b54126952..aac9a60b95 100644 --- a/vendor/github.com/gogits/cron/spec.go +++ b/vendor/github.com/gogs/cron/spec.go @@ -151,7 +151,6 @@ func dayMatches(s *SpecSchedule, t time.Time) bool { domMatch bool = 1<<uint(t.Day())&s.Dom > 0 dowMatch bool = 1<<uint(t.Weekday())&s.Dow > 0 ) - if s.Dom&starBit > 0 || s.Dow&starBit > 0 { return domMatch && dowMatch } |