mirror of
https://github.com/octoleo/restic.git
synced 2024-11-23 05:12:10 +00:00
Update vendored library github.com/go-ini/ini
This commit is contained in:
parent
0d01c27c9e
commit
874b3dbbd9
4
Gopkg.lock
generated
4
Gopkg.lock
generated
@ -58,8 +58,8 @@
|
|||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/go-ini/ini"
|
name = "github.com/go-ini/ini"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "32e4c1e6bc4e7d0d8451aa6b75200d19e37a536a"
|
revision = "6333e38ac20b8949a8dd68baa3650f4dee8f39f0"
|
||||||
version = "v1.32.0"
|
version = "v1.33.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
3
vendor/github.com/go-ini/ini/.travis.yml
generated
vendored
3
vendor/github.com/go-ini/ini/.travis.yml
generated
vendored
@ -6,8 +6,9 @@ go:
|
|||||||
- 1.7.x
|
- 1.7.x
|
||||||
- 1.8.x
|
- 1.8.x
|
||||||
- 1.9.x
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- go get golang.org/x/tools/cmd/cover
|
- go get golang.org/x/tools/cmd/cover
|
||||||
- go get github.com/smartystreets/goconvey
|
- go get github.com/smartystreets/goconvey
|
||||||
- mkdir -p $HOME/gopath/src/gopkg.in
|
- mkdir -p $HOME/gopath/src/gopkg.in
|
||||||
|
2
vendor/github.com/go-ini/ini/Makefile
generated
vendored
2
vendor/github.com/go-ini/ini/Makefile
generated
vendored
@ -12,4 +12,4 @@ vet:
|
|||||||
go vet
|
go vet
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out
|
go test -coverprofile=c.out && go tool cover -html=c.out && rm c.out
|
||||||
|
35
vendor/github.com/go-ini/ini/README.md
generated
vendored
35
vendor/github.com/go-ini/ini/README.md
generated
vendored
@ -87,7 +87,7 @@ key1, err := sec1.GetKey("Key")
|
|||||||
key2, err := sec2.GetKey("KeY")
|
key2, err := sec2.GetKey("KeY")
|
||||||
```
|
```
|
||||||
|
|
||||||
#### MySQL-like boolean key
|
#### MySQL-like boolean key
|
||||||
|
|
||||||
MySQL's configuration allows a key without value as follows:
|
MySQL's configuration allows a key without value as follows:
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ cfg, err := ini.LoadSources(ini.LoadOptions{
|
|||||||
}, "filename")
|
}, "filename")
|
||||||
```
|
```
|
||||||
|
|
||||||
Holy crap!
|
Holy crap!
|
||||||
|
|
||||||
Note that single quotes around values will be stripped:
|
Note that single quotes around values will be stripped:
|
||||||
|
|
||||||
@ -339,7 +339,7 @@ How do you transform this to regular format automatically?
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
|
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
|
||||||
cfg.Section("<name of your section>").Key("create_repo").String()
|
cfg.Section("<name of your section>").Key("create_repo").String()
|
||||||
// You got: created repository <a href="%s">%s</a>
|
// You got: created repository <a href="%s">%s</a>
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -440,7 +440,7 @@ By default, spaces are used to align "=" sign between key and values, to disable
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
ini.PrettyFormat = false
|
ini.PrettyFormat = false
|
||||||
```
|
```
|
||||||
|
|
||||||
## Advanced Usage
|
## Advanced Usage
|
||||||
|
|
||||||
@ -489,6 +489,33 @@ cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
|||||||
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Same Key with Multiple Values
|
||||||
|
|
||||||
|
Do you ever have a configuration file like this?
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[remote "origin"]
|
||||||
|
url = https://github.com/Antergone/test1.git
|
||||||
|
url = https://github.com/Antergone/test2.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
```
|
||||||
|
|
||||||
|
By default, only the last read value will be kept for the key `url`. If you want to keep all copies of value of this key, you can use `ShadowLoad` to achieve it:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := ini.ShadowLoad(".gitconfig")
|
||||||
|
// ...
|
||||||
|
|
||||||
|
f.Section(`remote "origin"`).Key("url").String()
|
||||||
|
// Result: https://github.com/Antergone/test1.git
|
||||||
|
|
||||||
|
f.Section(`remote "origin"`).Key("url").ValueWithShadows()
|
||||||
|
// Result: []string{
|
||||||
|
// "https://github.com/Antergone/test1.git",
|
||||||
|
// "https://github.com/Antergone/test2.git",
|
||||||
|
// }
|
||||||
|
```
|
||||||
|
|
||||||
### Unparseable Sections
|
### Unparseable Sections
|
||||||
|
|
||||||
Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`:
|
Sometimes, you have sections that do not contain key-value pairs but raw content, to handle such case, you can use `LoadOptions.UnparsableSections`:
|
||||||
|
31
vendor/github.com/go-ini/ini/README_ZH.md
generated
vendored
31
vendor/github.com/go-ini/ini/README_ZH.md
generated
vendored
@ -332,7 +332,7 @@ create_repo="创建了仓库 <a href=\"%s\">%s</a>"
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
|
cfg, err := ini.LoadSources(ini.LoadOptions{UnescapeValueDoubleQuotes: true}, "en-US.ini"))
|
||||||
cfg.Section("<name of your section>").Key("create_repo").String()
|
cfg.Section("<name of your section>").Key("create_repo").String()
|
||||||
// You got: 创建了仓库 <a href="%s">%s</a>
|
// You got: 创建了仓库 <a href="%s">%s</a>
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -433,7 +433,7 @@ cfg.WriteToIndent(writer, "\t")
|
|||||||
|
|
||||||
```go
|
```go
|
||||||
ini.PrettyFormat = false
|
ini.PrettyFormat = false
|
||||||
```
|
```
|
||||||
|
|
||||||
## 高级用法
|
## 高级用法
|
||||||
|
|
||||||
@ -482,6 +482,33 @@ cfg.Section("package.sub").Key("CLONE_URL").String() // https://gopkg.in/ini.v1
|
|||||||
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
cfg.Section("package.sub").ParentKeys() // ["CLONE_URL"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 同个键名包含多个值
|
||||||
|
|
||||||
|
你是否也曾被下面的配置文件所困扰?
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[remote "origin"]
|
||||||
|
url = https://github.com/Antergone/test1.git
|
||||||
|
url = https://github.com/Antergone/test2.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
```
|
||||||
|
|
||||||
|
没错!默认情况下,只有最后一次出现的值会被保存到 `url` 中,可我就是想要保留所有的值怎么办啊?不要紧,用 `ShadowLoad` 轻松解决你的烦恼:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cfg, err := ini.ShadowLoad(".gitconfig")
|
||||||
|
// ...
|
||||||
|
|
||||||
|
f.Section(`remote "origin"`).Key("url").String()
|
||||||
|
// Result: https://github.com/Antergone/test1.git
|
||||||
|
|
||||||
|
f.Section(`remote "origin"`).Key("url").ValueWithShadows()
|
||||||
|
// Result: []string{
|
||||||
|
// "https://github.com/Antergone/test1.git",
|
||||||
|
// "https://github.com/Antergone/test2.git",
|
||||||
|
// }
|
||||||
|
```
|
||||||
|
|
||||||
### 无法解析的分区
|
### 无法解析的分区
|
||||||
|
|
||||||
如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理:
|
如果遇到一些比较特殊的分区,它们不包含常见的键值对,而是没有固定格式的纯文本,则可以使用 `LoadOptions.UnparsableSections` 进行处理:
|
||||||
|
9
vendor/github.com/go-ini/ini/file.go
generated
vendored
9
vendor/github.com/go-ini/ini/file.go
generated
vendored
@ -140,9 +140,14 @@ func (f *File) Section(name string) *Section {
|
|||||||
|
|
||||||
// Section returns list of Section.
|
// Section returns list of Section.
|
||||||
func (f *File) Sections() []*Section {
|
func (f *File) Sections() []*Section {
|
||||||
|
if f.BlockMode {
|
||||||
|
f.lock.RLock()
|
||||||
|
defer f.lock.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
sections := make([]*Section, len(f.sectionList))
|
sections := make([]*Section, len(f.sectionList))
|
||||||
for i := range f.sectionList {
|
for i, name := range f.sectionList {
|
||||||
sections[i] = f.Section(f.sectionList[i])
|
sections[i] = f.sections[name]
|
||||||
}
|
}
|
||||||
return sections
|
return sections
|
||||||
}
|
}
|
||||||
|
93
vendor/github.com/go-ini/ini/file_test.go
generated
vendored
93
vendor/github.com/go-ini/ini/file_test.go
generated
vendored
@ -16,6 +16,7 @@ package ini_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
@ -253,93 +254,15 @@ func TestFile_WriteTo(t *testing.T) {
|
|||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
_, err = f.WriteTo(&buf)
|
_, err = f.WriteTo(&buf)
|
||||||
So(err, ShouldBeNil)
|
So(err, ShouldBeNil)
|
||||||
So(buf.String(), ShouldEqual, `; Package name
|
|
||||||
NAME = ini
|
|
||||||
; Package version
|
|
||||||
VERSION = v1
|
|
||||||
; Package import path
|
|
||||||
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
|
|
||||||
|
|
||||||
; Information about package author
|
golden := "testdata/TestFile_WriteTo.golden"
|
||||||
# Bio can be written in multiple lines.
|
if *update {
|
||||||
[author]
|
ioutil.WriteFile(golden, buf.Bytes(), 0644)
|
||||||
; This is author name
|
}
|
||||||
NAME = Unknwon
|
|
||||||
E-MAIL = u@gogs.io
|
|
||||||
GITHUB = https://github.com/%(NAME)s
|
|
||||||
# Succeeding comment
|
|
||||||
BIO = """Gopher.
|
|
||||||
Coding addict.
|
|
||||||
Good man.
|
|
||||||
"""
|
|
||||||
|
|
||||||
[package]
|
expected, err := ioutil.ReadFile(golden)
|
||||||
CLONE_URL = https://%(IMPORT_PATH)s
|
So(err, ShouldBeNil)
|
||||||
|
So(buf.String(), ShouldEqual, string(expected))
|
||||||
[package.sub]
|
|
||||||
UNUSED_KEY = should be deleted
|
|
||||||
|
|
||||||
[features]
|
|
||||||
- = Support read/write comments of keys and sections
|
|
||||||
- = Support auto-increment of key names
|
|
||||||
- = Support load multiple files to overwrite key values
|
|
||||||
|
|
||||||
[types]
|
|
||||||
STRING = str
|
|
||||||
BOOL = true
|
|
||||||
BOOL_FALSE = false
|
|
||||||
FLOAT64 = 1.25
|
|
||||||
INT = 10
|
|
||||||
TIME = 2015-01-01T20:17:05Z
|
|
||||||
DURATION = 2h45m
|
|
||||||
UINT = 3
|
|
||||||
|
|
||||||
[array]
|
|
||||||
STRINGS = en, zh, de
|
|
||||||
FLOAT64S = 1.1, 2.2, 3.3
|
|
||||||
INTS = 1, 2, 3
|
|
||||||
UINTS = 1, 2, 3
|
|
||||||
TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
|
|
||||||
|
|
||||||
[note]
|
|
||||||
empty_lines = next line is empty
|
|
||||||
boolean_key
|
|
||||||
more = notes
|
|
||||||
|
|
||||||
; Comment before the section
|
|
||||||
; This is a comment for the section too
|
|
||||||
[comments]
|
|
||||||
; Comment before key
|
|
||||||
key = value
|
|
||||||
; This is a comment for key2
|
|
||||||
key2 = value2
|
|
||||||
key3 = "one", "two", "three"
|
|
||||||
|
|
||||||
[string escapes]
|
|
||||||
key1 = value1, value2, value3
|
|
||||||
key2 = value1\, value2
|
|
||||||
key3 = val\ue1, value2
|
|
||||||
key4 = value1\\, value\\\\2
|
|
||||||
key5 = value1\,, value2
|
|
||||||
key6 = aaa bbb\ and\ space ccc
|
|
||||||
|
|
||||||
[advance]
|
|
||||||
value with quotes = some value
|
|
||||||
value quote2 again = some value
|
|
||||||
includes comment sign = `+"`"+"my#password"+"`"+`
|
|
||||||
includes comment sign2 = `+"`"+"my;password"+"`"+`
|
|
||||||
true = 2+3=5
|
|
||||||
`+"`"+`1+1=2`+"`"+` = true
|
|
||||||
`+"`"+`6+1=7`+"`"+` = true
|
|
||||||
"""`+"`"+`5+5`+"`"+`""" = 10
|
|
||||||
`+"`"+`"6+6"`+"`"+` = 12
|
|
||||||
`+"`"+`7-2=4`+"`"+` = false
|
|
||||||
ADDRESS = """404 road,
|
|
||||||
NotFound, State, 50000"""
|
|
||||||
two_lines = how about continuation lines?
|
|
||||||
lots_of_lines = 1 2 3 4
|
|
||||||
|
|
||||||
`)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/github.com/go-ini/ini/ini.go
generated
vendored
2
vendor/github.com/go-ini/ini/ini.go
generated
vendored
@ -32,7 +32,7 @@ const (
|
|||||||
|
|
||||||
// Maximum allowed depth when recursively substituing variable names.
|
// Maximum allowed depth when recursively substituing variable names.
|
||||||
_DEPTH_VALUES = 99
|
_DEPTH_VALUES = 99
|
||||||
_VERSION = "1.32.0"
|
_VERSION = "1.33.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version returns current package version literal.
|
// Version returns current package version literal.
|
||||||
|
3
vendor/github.com/go-ini/ini/ini_test.go
generated
vendored
3
vendor/github.com/go-ini/ini/ini_test.go
generated
vendored
@ -16,6 +16,7 @@ package ini_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"flag"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -47,6 +48,8 @@ const (
|
|||||||
_NOT_FOUND_CONF = "testdata/404.ini"
|
_NOT_FOUND_CONF = "testdata/404.ini"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var update = flag.Bool("update", false, "Update .golden files")
|
||||||
|
|
||||||
func TestLoad(t *testing.T) {
|
func TestLoad(t *testing.T) {
|
||||||
Convey("Load from good data sources", t, func() {
|
Convey("Load from good data sources", t, func() {
|
||||||
f, err := ini.Load([]byte(`
|
f, err := ini.Load([]byte(`
|
||||||
|
10
vendor/github.com/go-ini/ini/struct_test.go
generated
vendored
10
vendor/github.com/go-ini/ini/struct_test.go
generated
vendored
@ -37,7 +37,7 @@ type testNested struct {
|
|||||||
Unused int `ini:"-"`
|
Unused int `ini:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type testEmbeded struct {
|
type TestEmbeded struct {
|
||||||
GPA float64
|
GPA float64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ type testStruct struct {
|
|||||||
Born time.Time
|
Born time.Time
|
||||||
Time time.Duration `ini:"Duration"`
|
Time time.Duration `ini:"Duration"`
|
||||||
Others testNested
|
Others testNested
|
||||||
*testEmbeded `ini:"grade"`
|
*TestEmbeded `ini:"grade"`
|
||||||
Unused int `ini:"-"`
|
Unused int `ini:"-"`
|
||||||
Unsigned uint
|
Unsigned uint
|
||||||
Omitted bool `ini:"omitthis,omitempty"`
|
Omitted bool `ini:"omitthis,omitempty"`
|
||||||
@ -97,12 +97,12 @@ type unsupport2 struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type unsupport3 struct {
|
type Unsupport3 struct {
|
||||||
Cities byte
|
Cities byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type unsupport4 struct {
|
type unsupport4 struct {
|
||||||
*unsupport3 `ini:"Others"`
|
*Unsupport3 `ini:"Others"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type defaultValue struct {
|
type defaultValue struct {
|
||||||
@ -155,7 +155,7 @@ func Test_MapToStruct(t *testing.T) {
|
|||||||
So(fmt.Sprint(ts.Others.Populations), ShouldEqual, "[12345678 98765432]")
|
So(fmt.Sprint(ts.Others.Populations), ShouldEqual, "[12345678 98765432]")
|
||||||
So(fmt.Sprint(ts.Others.Coordinates), ShouldEqual, "[192.168 10.11]")
|
So(fmt.Sprint(ts.Others.Coordinates), ShouldEqual, "[192.168 10.11]")
|
||||||
So(ts.Others.Note, ShouldEqual, "Hello world!")
|
So(ts.Others.Note, ShouldEqual, "Hello world!")
|
||||||
So(ts.testEmbeded.GPA, ShouldEqual, 2.8)
|
So(ts.TestEmbeded.GPA, ShouldEqual, 2.8)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Map section to struct", func() {
|
Convey("Map section to struct", func() {
|
||||||
|
86
vendor/github.com/go-ini/ini/testdata/TestFile_WriteTo.golden
generated
vendored
Normal file
86
vendor/github.com/go-ini/ini/testdata/TestFile_WriteTo.golden
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
; Package name
|
||||||
|
NAME = ini
|
||||||
|
; Package version
|
||||||
|
VERSION = v1
|
||||||
|
; Package import path
|
||||||
|
IMPORT_PATH = gopkg.in/%(NAME)s.%(VERSION)s
|
||||||
|
|
||||||
|
; Information about package author
|
||||||
|
# Bio can be written in multiple lines.
|
||||||
|
[author]
|
||||||
|
; This is author name
|
||||||
|
NAME = Unknwon
|
||||||
|
E-MAIL = u@gogs.io
|
||||||
|
GITHUB = https://github.com/%(NAME)s
|
||||||
|
# Succeeding comment
|
||||||
|
BIO = """Gopher.
|
||||||
|
Coding addict.
|
||||||
|
Good man.
|
||||||
|
"""
|
||||||
|
|
||||||
|
[package]
|
||||||
|
CLONE_URL = https://%(IMPORT_PATH)s
|
||||||
|
|
||||||
|
[package.sub]
|
||||||
|
UNUSED_KEY = should be deleted
|
||||||
|
|
||||||
|
[features]
|
||||||
|
- = Support read/write comments of keys and sections
|
||||||
|
- = Support auto-increment of key names
|
||||||
|
- = Support load multiple files to overwrite key values
|
||||||
|
|
||||||
|
[types]
|
||||||
|
STRING = str
|
||||||
|
BOOL = true
|
||||||
|
BOOL_FALSE = false
|
||||||
|
FLOAT64 = 1.25
|
||||||
|
INT = 10
|
||||||
|
TIME = 2015-01-01T20:17:05Z
|
||||||
|
DURATION = 2h45m
|
||||||
|
UINT = 3
|
||||||
|
|
||||||
|
[array]
|
||||||
|
STRINGS = en, zh, de
|
||||||
|
FLOAT64S = 1.1, 2.2, 3.3
|
||||||
|
INTS = 1, 2, 3
|
||||||
|
UINTS = 1, 2, 3
|
||||||
|
TIMES = 2015-01-01T20:17:05Z,2015-01-01T20:17:05Z,2015-01-01T20:17:05Z
|
||||||
|
|
||||||
|
[note]
|
||||||
|
empty_lines = next line is empty
|
||||||
|
boolean_key
|
||||||
|
more = notes
|
||||||
|
|
||||||
|
; Comment before the section
|
||||||
|
; This is a comment for the section too
|
||||||
|
[comments]
|
||||||
|
; Comment before key
|
||||||
|
key = value
|
||||||
|
; This is a comment for key2
|
||||||
|
key2 = value2
|
||||||
|
key3 = "one", "two", "three"
|
||||||
|
|
||||||
|
[string escapes]
|
||||||
|
key1 = value1, value2, value3
|
||||||
|
key2 = value1\, value2
|
||||||
|
key3 = val\ue1, value2
|
||||||
|
key4 = value1\\, value\\\\2
|
||||||
|
key5 = value1\,, value2
|
||||||
|
key6 = aaa bbb\ and\ space ccc
|
||||||
|
|
||||||
|
[advance]
|
||||||
|
value with quotes = some value
|
||||||
|
value quote2 again = some value
|
||||||
|
includes comment sign = `my#password`
|
||||||
|
includes comment sign2 = `my;password`
|
||||||
|
true = 2+3=5
|
||||||
|
`1+1=2` = true
|
||||||
|
`6+1=7` = true
|
||||||
|
"""`5+5`""" = 10
|
||||||
|
`"6+6"` = 12
|
||||||
|
`7-2=4` = false
|
||||||
|
ADDRESS = """404 road,
|
||||||
|
NotFound, State, 50000"""
|
||||||
|
two_lines = how about continuation lines?
|
||||||
|
lots_of_lines = 1 2 3 4
|
||||||
|
|
Loading…
Reference in New Issue
Block a user