MM-27918 In-Product notices support (#15316)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
43ed6ad690
Коммит
4e9ddd4686
3
vendor/github.com/reflog/dateconstraints/.gitignore
сгенерированный
поставляемый
Обычный файл
3
vendor/github.com/reflog/dateconstraints/.gitignore
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,3 @@
|
||||
.vscode
|
||||
.idea
|
||||
*.iml
|
||||
21
vendor/github.com/reflog/dateconstraints/LICENSE
сгенерированный
поставляемый
Обычный файл
21
vendor/github.com/reflog/dateconstraints/LICENSE
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) [year] [fullname]
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
84
vendor/github.com/reflog/dateconstraints/README.md
сгенерированный
поставляемый
Обычный файл
84
vendor/github.com/reflog/dateconstraints/README.md
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,84 @@
|
||||
# Date Constraints
|
||||
|
||||
### Validate a date against constraints
|
||||
|
||||
## Overview [](https://godoc.org/github.com/reflog/dateconstraints)
|
||||
|
||||
This module is heavily based on https://github.com/Masterminds/semver so kudos to [Masterminds](https://github.com/Masterminds/semver).
|
||||
|
||||
> _For now only RFC3339 dates are supported_
|
||||
|
||||
## Basic Comparisons
|
||||
|
||||
There are two elements to the comparisons. First, a comparison string is a list
|
||||
of space or comma separated AND comparisons. These are then separated by || (OR)
|
||||
comparisons. For example, `">= 2020-03-01T00:00:00Z < 2020-04-01T00:00:00Z || >= 2020-05-01T00:00:00Z"` is will validate if a date is between 01/03/2020 till 01/04/2020 OR it's after 01/05/2020.
|
||||
|
||||
The basic comparisons are:
|
||||
|
||||
- `=`: equal
|
||||
- `!=`: not equal
|
||||
- `>`: greater than
|
||||
- `<`: less than
|
||||
- `>=`: greater than or equal to
|
||||
- `<=`: less than or equal to
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
|
||||
import "github.com/reflog/dateconstraints"
|
||||
import "time"
|
||||
|
||||
func main(){
|
||||
|
||||
date, _ := time.Parse(time.RFC3339, "2020-03-10T00:00:00Z")
|
||||
c, _ := date_constraints.NewConstraint("> 2020-03-01T00:00:00Z <= 2020-04-01T00:00:00Z")
|
||||
if c.Check(&date) {
|
||||
// date is in range!
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
In addition to testing a date against a constraint, it can be validated
|
||||
against a constraint. When validation fails a slice of errors containing why a
|
||||
date didn't meet the constraint is returned. For example,
|
||||
|
||||
```go
|
||||
c, err := date_constraints.NewConstraint("<= 2020-03-01T00:00:00Z, >= 2020-04-10T00:00:00Z")
|
||||
if err != nil {
|
||||
// Handle constraint not being parseable.
|
||||
}
|
||||
v, err := time.Parse(time.RFC3339, "2020-03-10T00:00:00Z")
|
||||
if err != nil {
|
||||
// Handle date not being parseable.
|
||||
}
|
||||
// Validate a date against a constraint.
|
||||
a, msgs := c.Validate(&v)
|
||||
// a is false
|
||||
for _, m := range msgs {
|
||||
fmt.Println(m)
|
||||
// Loops over the errors which would read
|
||||
// "2020-03-10T00:00:00Z is greater than 2020-03-01T00:00:00Z"
|
||||
// "2020-03-01T00:00:00Z is less than 2020-04-01T00:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
go get github.com/reflog/dateconstraints
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
||||
|
||||
Please make sure to update tests as appropriate.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://choosealicense.com/licenses/mit/)
|
||||
277
vendor/github.com/reflog/dateconstraints/constraints.go
сгенерированный
поставляемый
Обычный файл
277
vendor/github.com/reflog/dateconstraints/constraints.go
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,277 @@
|
||||
package date_constraints
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Constraints is one or more constraint that a date can be
|
||||
// checked against.
|
||||
type Constraints struct {
|
||||
constraints [][]*constraint
|
||||
}
|
||||
|
||||
// NewConstraint returns a Constraints instance that a time.Time instance can
|
||||
// be checked against. If there is a parse error it will be returned.
|
||||
func NewConstraint(c string) (*Constraints, error) {
|
||||
|
||||
// Rewrite - ranges into a comparison operation.
|
||||
c = rewriteRange(c)
|
||||
|
||||
ors := strings.Split(c, "||")
|
||||
or := make([][]*constraint, len(ors))
|
||||
for k, v := range ors {
|
||||
|
||||
// TODO: Find a way to validate and fetch all the constraints in a simpler form
|
||||
|
||||
// Validate the segment
|
||||
if !validConstraintRegex.MatchString(v) {
|
||||
return nil, fmt.Errorf("improper constraint: %s", v)
|
||||
}
|
||||
|
||||
cs := findConstraintRegex.FindAllString(v, -1)
|
||||
if cs == nil {
|
||||
cs = append(cs, v)
|
||||
}
|
||||
result := make([]*constraint, len(cs))
|
||||
for i, s := range cs {
|
||||
pc, err := parseConstraint(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result[i] = pc
|
||||
}
|
||||
or[k] = result
|
||||
}
|
||||
|
||||
o := &Constraints{constraints: or}
|
||||
return o, nil
|
||||
}
|
||||
|
||||
// Check tests if a date satisfies the constraints.
|
||||
func (cs Constraints) Check(v *time.Time) bool {
|
||||
for _, o := range cs.constraints {
|
||||
joy := true
|
||||
for _, c := range o {
|
||||
if check, _ := c.check(v); !check {
|
||||
joy = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if joy {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Validate checks if a date satisfies a constraint. If not a slice of
|
||||
// reasons for the failure are returned in addition to a bool.
|
||||
func (cs Constraints) Validate(v *time.Time) (bool, []error) {
|
||||
// loop over the ORs and check the inner ANDs
|
||||
var e []error
|
||||
|
||||
for _, o := range cs.constraints {
|
||||
joy := true
|
||||
for _, c := range o {
|
||||
if _, err := c.check(v); err != nil {
|
||||
e = append(e, err)
|
||||
joy = false
|
||||
}
|
||||
}
|
||||
|
||||
if joy {
|
||||
return true, []error{}
|
||||
}
|
||||
}
|
||||
|
||||
return false, e
|
||||
}
|
||||
|
||||
func (cs Constraints) String() string {
|
||||
buf := make([]string, len(cs.constraints))
|
||||
var tmp bytes.Buffer
|
||||
|
||||
for k, v := range cs.constraints {
|
||||
tmp.Reset()
|
||||
vlen := len(v)
|
||||
for kk, c := range v {
|
||||
tmp.WriteString(c.string())
|
||||
|
||||
// Space separate the AND conditions
|
||||
if vlen > 1 && kk < vlen-1 {
|
||||
tmp.WriteString(" ")
|
||||
}
|
||||
}
|
||||
buf[k] = tmp.String()
|
||||
}
|
||||
|
||||
return strings.Join(buf, " || ")
|
||||
}
|
||||
|
||||
var constraintOps map[string]cfunc
|
||||
var constraintRegex *regexp.Regexp
|
||||
var constraintRangeRegex *regexp.Regexp
|
||||
|
||||
// Used to find individual constraints within a multi-constraint string
|
||||
var findConstraintRegex *regexp.Regexp
|
||||
|
||||
// Used to validate an segment of ANDs is valid
|
||||
var validConstraintRegex *regexp.Regexp
|
||||
|
||||
const cvRegex string = `\d{4}(-\d\d(-\d\d(T\d\d:\d\d(:\d\d)?(\.\d+)?(([+-]\d\d:\d\d)|Z)?)?)?)?`
|
||||
|
||||
func init() {
|
||||
constraintOps = map[string]cfunc{
|
||||
"!=": constraintNotEqual,
|
||||
"=": constraintEqual,
|
||||
">": constraintGreaterThan,
|
||||
"<": constraintLessThan,
|
||||
">=": constraintGreaterThanEqual,
|
||||
"=>": constraintGreaterThanEqual,
|
||||
"<=": constraintLessThanEqual,
|
||||
"=<": constraintLessThanEqual,
|
||||
}
|
||||
|
||||
ops := make([]string, 0, len(constraintOps))
|
||||
for k := range constraintOps {
|
||||
ops = append(ops, regexp.QuoteMeta(k))
|
||||
}
|
||||
|
||||
constraintRegex = regexp.MustCompile(fmt.Sprintf(
|
||||
`^\s*(%s)\s*(%s)\s*$`,
|
||||
strings.Join(ops, "|"),
|
||||
cvRegex))
|
||||
|
||||
constraintRangeRegex = regexp.MustCompile(fmt.Sprintf(
|
||||
`\s*(%s)\s+-\s+(%s)\s*`,
|
||||
cvRegex, cvRegex))
|
||||
|
||||
findConstraintRegex = regexp.MustCompile(fmt.Sprintf(
|
||||
`(%s)\s*(%s)`,
|
||||
strings.Join(ops, "|"),
|
||||
cvRegex))
|
||||
|
||||
validConstraintRegex = regexp.MustCompile(fmt.Sprintf(
|
||||
`^(\s*(%s)\s*(%s)\s*\,?)+$`,
|
||||
strings.Join(ops, "|"),
|
||||
cvRegex))
|
||||
}
|
||||
|
||||
// An individual constraint
|
||||
type constraint struct {
|
||||
// The time used in the constraint check. For example, if a constraint
|
||||
// is '<= 2020-03-01T00:00:00Z' then con is an instance representing 2020-03-01T00:00:00Z.
|
||||
con *time.Time
|
||||
|
||||
// The original parsed date (e.g., 2020-03-01T00:00:00Z)
|
||||
orig string
|
||||
|
||||
// The original operator for the constraint (e.g. <=)
|
||||
origfunc string
|
||||
}
|
||||
|
||||
// Check if a date meets the constraint
|
||||
func (c *constraint) check(v *time.Time) (bool, error) {
|
||||
return constraintOps[c.origfunc](v, c)
|
||||
}
|
||||
|
||||
// String prints an individual constraint into a string
|
||||
func (c *constraint) string() string {
|
||||
return c.origfunc + c.orig
|
||||
}
|
||||
|
||||
type cfunc func(v *time.Time, c *constraint) (bool, error)
|
||||
|
||||
func parseConstraint(c string) (*constraint, error) {
|
||||
if len(c) > 0 {
|
||||
m := constraintRegex.FindStringSubmatch(c)
|
||||
if m == nil {
|
||||
return nil, fmt.Errorf("improper constraint: %s", c)
|
||||
}
|
||||
|
||||
cs := &constraint{
|
||||
orig: m[2],
|
||||
origfunc: m[1],
|
||||
}
|
||||
|
||||
con, err := time.Parse(time.RFC3339, m[2])
|
||||
if err != nil {
|
||||
|
||||
// The constraintRegex should catch any regex parsing errors. So,
|
||||
// we should never get here.
|
||||
return nil, errors.New("constraint Parser Error")
|
||||
}
|
||||
|
||||
cs.con = &con
|
||||
|
||||
return cs, nil
|
||||
}
|
||||
return nil, errors.New("constraint Parser Error")
|
||||
}
|
||||
|
||||
// Constraint functions
|
||||
func constraintNotEqual(v *time.Time, c *constraint) (bool, error) {
|
||||
if v.Equal(*c.con) {
|
||||
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func constraintEqual(v *time.Time, c *constraint) (bool, error) {
|
||||
if !v.Equal(*c.con) {
|
||||
return false, fmt.Errorf("%s is not equal to %s", v, c.orig)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func constraintGreaterThan(v *time.Time, c *constraint) (bool, error) {
|
||||
if v.After(*c.con) {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
|
||||
}
|
||||
|
||||
func constraintLessThan(v *time.Time, c *constraint) (bool, error) {
|
||||
if v.Before(*c.con) {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("%s is greater than or equal to %s", v, c.orig)
|
||||
}
|
||||
|
||||
func constraintGreaterThanEqual(v *time.Time, c *constraint) (bool, error) {
|
||||
if v.After(*c.con) || v.Equal(*c.con) {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("%s is less than %s", v, c.orig)
|
||||
}
|
||||
|
||||
func constraintLessThanEqual(v *time.Time, c *constraint) (bool, error) {
|
||||
if v.Before(*c.con) || v.Equal(*c.con) {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
|
||||
}
|
||||
|
||||
func rewriteRange(i string) string {
|
||||
m := constraintRangeRegex.FindAllStringSubmatch(i, -1)
|
||||
if m == nil {
|
||||
return i
|
||||
}
|
||||
o := i
|
||||
for _, v := range m {
|
||||
t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
|
||||
o = strings.Replace(o, v[0], t, 1)
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
5
vendor/github.com/reflog/dateconstraints/go.mod
сгенерированный
поставляемый
Обычный файл
5
vendor/github.com/reflog/dateconstraints/go.mod
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,5 @@
|
||||
module github.com/reflog/dateconstraints
|
||||
|
||||
go 1.14
|
||||
|
||||
require github.com/stretchr/testify v1.6.1
|
||||
11
vendor/github.com/reflog/dateconstraints/go.sum
сгенерированный
поставляемый
Обычный файл
11
vendor/github.com/reflog/dateconstraints/go.sum
сгенерированный
поставляемый
Обычный файл
@@ -0,0 +1,11 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
Ссылка в новой задаче
Block a user