Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
songlinfeng
container-toolkit
Commits
ae831b78
Commit
ae831b78
authored
Oct 28, 2025
by
songlinfeng
Browse files
add support podman
parent
3e3a4e74
Changes
24
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1526 additions
and
0 deletions
+1526
-0
vendor/gopkg.in/ini.v1/parser.go
vendor/gopkg.in/ini.v1/parser.go
+520
-0
vendor/gopkg.in/ini.v1/section.go
vendor/gopkg.in/ini.v1/section.go
+256
-0
vendor/gopkg.in/ini.v1/struct.go
vendor/gopkg.in/ini.v1/struct.go
+747
-0
vendor/modules.txt
vendor/modules.txt
+3
-0
No files found.
vendor/gopkg.in/ini.v1/parser.go
0 → 100644
View file @
ae831b78
// Copyright 2015 Unknwon
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package
ini
import
(
"bufio"
"bytes"
"fmt"
"io"
"regexp"
"strconv"
"strings"
"unicode"
)
const
minReaderBufferSize
=
4096
var
pythonMultiline
=
regexp
.
MustCompile
(
`^([\t\f ]+)(.*)`
)
type
parserOptions
struct
{
IgnoreContinuation
bool
IgnoreInlineComment
bool
AllowPythonMultilineValues
bool
SpaceBeforeInlineComment
bool
UnescapeValueDoubleQuotes
bool
UnescapeValueCommentSymbols
bool
PreserveSurroundedQuote
bool
DebugFunc
DebugFunc
ReaderBufferSize
int
}
type
parser
struct
{
buf
*
bufio
.
Reader
options
parserOptions
isEOF
bool
count
int
comment
*
bytes
.
Buffer
}
func
(
p
*
parser
)
debug
(
format
string
,
args
...
interface
{})
{
if
p
.
options
.
DebugFunc
!=
nil
{
p
.
options
.
DebugFunc
(
fmt
.
Sprintf
(
format
,
args
...
))
}
}
func
newParser
(
r
io
.
Reader
,
opts
parserOptions
)
*
parser
{
size
:=
opts
.
ReaderBufferSize
if
size
<
minReaderBufferSize
{
size
=
minReaderBufferSize
}
return
&
parser
{
buf
:
bufio
.
NewReaderSize
(
r
,
size
),
options
:
opts
,
count
:
1
,
comment
:
&
bytes
.
Buffer
{},
}
}
// BOM handles header of UTF-8, UTF-16 LE and UTF-16 BE's BOM format.
// http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding
func
(
p
*
parser
)
BOM
()
error
{
mask
,
err
:=
p
.
buf
.
Peek
(
2
)
if
err
!=
nil
&&
err
!=
io
.
EOF
{
return
err
}
else
if
len
(
mask
)
<
2
{
return
nil
}
switch
{
case
mask
[
0
]
==
254
&&
mask
[
1
]
==
255
:
fallthrough
case
mask
[
0
]
==
255
&&
mask
[
1
]
==
254
:
_
,
err
=
p
.
buf
.
Read
(
mask
)
if
err
!=
nil
{
return
err
}
case
mask
[
0
]
==
239
&&
mask
[
1
]
==
187
:
mask
,
err
:=
p
.
buf
.
Peek
(
3
)
if
err
!=
nil
&&
err
!=
io
.
EOF
{
return
err
}
else
if
len
(
mask
)
<
3
{
return
nil
}
if
mask
[
2
]
==
191
{
_
,
err
=
p
.
buf
.
Read
(
mask
)
if
err
!=
nil
{
return
err
}
}
}
return
nil
}
func
(
p
*
parser
)
readUntil
(
delim
byte
)
([]
byte
,
error
)
{
data
,
err
:=
p
.
buf
.
ReadBytes
(
delim
)
if
err
!=
nil
{
if
err
==
io
.
EOF
{
p
.
isEOF
=
true
}
else
{
return
nil
,
err
}
}
return
data
,
nil
}
func
cleanComment
(
in
[]
byte
)
([]
byte
,
bool
)
{
i
:=
bytes
.
IndexAny
(
in
,
"#;"
)
if
i
==
-
1
{
return
nil
,
false
}
return
in
[
i
:
],
true
}
func
readKeyName
(
delimiters
string
,
in
[]
byte
)
(
string
,
int
,
error
)
{
line
:=
string
(
in
)
// Check if key name surrounded by quotes.
var
keyQuote
string
if
line
[
0
]
==
'"'
{
if
len
(
line
)
>
6
&&
line
[
0
:
3
]
==
`"""`
{
keyQuote
=
`"""`
}
else
{
keyQuote
=
`"`
}
}
else
if
line
[
0
]
==
'`'
{
keyQuote
=
"`"
}
// Get out key name
var
endIdx
int
if
len
(
keyQuote
)
>
0
{
startIdx
:=
len
(
keyQuote
)
// FIXME: fail case -> """"""name"""=value
pos
:=
strings
.
Index
(
line
[
startIdx
:
],
keyQuote
)
if
pos
==
-
1
{
return
""
,
-
1
,
fmt
.
Errorf
(
"missing closing key quote: %s"
,
line
)
}
pos
+=
startIdx
// Find key-value delimiter
i
:=
strings
.
IndexAny
(
line
[
pos
+
startIdx
:
],
delimiters
)
if
i
<
0
{
return
""
,
-
1
,
ErrDelimiterNotFound
{
line
}
}
endIdx
=
pos
+
i
return
strings
.
TrimSpace
(
line
[
startIdx
:
pos
]),
endIdx
+
startIdx
+
1
,
nil
}
endIdx
=
strings
.
IndexAny
(
line
,
delimiters
)
if
endIdx
<
0
{
return
""
,
-
1
,
ErrDelimiterNotFound
{
line
}
}
if
endIdx
==
0
{
return
""
,
-
1
,
ErrEmptyKeyName
{
line
}
}
return
strings
.
TrimSpace
(
line
[
0
:
endIdx
]),
endIdx
+
1
,
nil
}
func
(
p
*
parser
)
readMultilines
(
line
,
val
,
valQuote
string
)
(
string
,
error
)
{
for
{
data
,
err
:=
p
.
readUntil
(
'\n'
)
if
err
!=
nil
{
return
""
,
err
}
next
:=
string
(
data
)
pos
:=
strings
.
LastIndex
(
next
,
valQuote
)
if
pos
>
-
1
{
val
+=
next
[
:
pos
]
comment
,
has
:=
cleanComment
([]
byte
(
next
[
pos
:
]))
if
has
{
p
.
comment
.
Write
(
bytes
.
TrimSpace
(
comment
))
}
break
}
val
+=
next
if
p
.
isEOF
{
return
""
,
fmt
.
Errorf
(
"missing closing key quote from %q to %q"
,
line
,
next
)
}
}
return
val
,
nil
}
func
(
p
*
parser
)
readContinuationLines
(
val
string
)
(
string
,
error
)
{
for
{
data
,
err
:=
p
.
readUntil
(
'\n'
)
if
err
!=
nil
{
return
""
,
err
}
next
:=
strings
.
TrimSpace
(
string
(
data
))
if
len
(
next
)
==
0
{
break
}
val
+=
next
if
val
[
len
(
val
)
-
1
]
!=
'\\'
{
break
}
val
=
val
[
:
len
(
val
)
-
1
]
}
return
val
,
nil
}
// hasSurroundedQuote check if and only if the first and last characters
// are quotes \" or \'.
// It returns false if any other parts also contain same kind of quotes.
func
hasSurroundedQuote
(
in
string
,
quote
byte
)
bool
{
return
len
(
in
)
>=
2
&&
in
[
0
]
==
quote
&&
in
[
len
(
in
)
-
1
]
==
quote
&&
strings
.
IndexByte
(
in
[
1
:
],
quote
)
==
len
(
in
)
-
2
}
func
(
p
*
parser
)
readValue
(
in
[]
byte
,
bufferSize
int
)
(
string
,
error
)
{
line
:=
strings
.
TrimLeftFunc
(
string
(
in
),
unicode
.
IsSpace
)
if
len
(
line
)
==
0
{
if
p
.
options
.
AllowPythonMultilineValues
&&
len
(
in
)
>
0
&&
in
[
len
(
in
)
-
1
]
==
'\n'
{
return
p
.
readPythonMultilines
(
line
,
bufferSize
)
}
return
""
,
nil
}
var
valQuote
string
if
len
(
line
)
>
3
&&
line
[
0
:
3
]
==
`"""`
{
valQuote
=
`"""`
}
else
if
line
[
0
]
==
'`'
{
valQuote
=
"`"
}
else
if
p
.
options
.
UnescapeValueDoubleQuotes
&&
line
[
0
]
==
'"'
{
valQuote
=
`"`
}
if
len
(
valQuote
)
>
0
{
startIdx
:=
len
(
valQuote
)
pos
:=
strings
.
LastIndex
(
line
[
startIdx
:
],
valQuote
)
// Check for multi-line value
if
pos
==
-
1
{
return
p
.
readMultilines
(
line
,
line
[
startIdx
:
],
valQuote
)
}
if
p
.
options
.
UnescapeValueDoubleQuotes
&&
valQuote
==
`"`
{
return
strings
.
Replace
(
line
[
startIdx
:
pos
+
startIdx
],
`\"`
,
`"`
,
-
1
),
nil
}
return
line
[
startIdx
:
pos
+
startIdx
],
nil
}
lastChar
:=
line
[
len
(
line
)
-
1
]
// Won't be able to reach here if value only contains whitespace
line
=
strings
.
TrimSpace
(
line
)
trimmedLastChar
:=
line
[
len
(
line
)
-
1
]
// Check continuation lines when desired
if
!
p
.
options
.
IgnoreContinuation
&&
trimmedLastChar
==
'\\'
{
return
p
.
readContinuationLines
(
line
[
:
len
(
line
)
-
1
])
}
// Check if ignore inline comment
if
!
p
.
options
.
IgnoreInlineComment
{
var
i
int
if
p
.
options
.
SpaceBeforeInlineComment
{
i
=
strings
.
Index
(
line
,
" #"
)
if
i
==
-
1
{
i
=
strings
.
Index
(
line
,
" ;"
)
}
}
else
{
i
=
strings
.
IndexAny
(
line
,
"#;"
)
}
if
i
>
-
1
{
p
.
comment
.
WriteString
(
line
[
i
:
])
line
=
strings
.
TrimSpace
(
line
[
:
i
])
}
}
// Trim single and double quotes
if
(
hasSurroundedQuote
(
line
,
'\'
'
)
||
hasSurroundedQuote
(
line
,
'"'
))
&&
!
p
.
options
.
PreserveSurroundedQuote
{
line
=
line
[
1
:
len
(
line
)
-
1
]
}
else
if
len
(
valQuote
)
==
0
&&
p
.
options
.
UnescapeValueCommentSymbols
{
line
=
strings
.
ReplaceAll
(
line
,
`\;`
,
";"
)
line
=
strings
.
ReplaceAll
(
line
,
`\#`
,
"#"
)
}
else
if
p
.
options
.
AllowPythonMultilineValues
&&
lastChar
==
'\n'
{
return
p
.
readPythonMultilines
(
line
,
bufferSize
)
}
return
line
,
nil
}
func
(
p
*
parser
)
readPythonMultilines
(
line
string
,
bufferSize
int
)
(
string
,
error
)
{
parserBufferPeekResult
,
_
:=
p
.
buf
.
Peek
(
bufferSize
)
peekBuffer
:=
bytes
.
NewBuffer
(
parserBufferPeekResult
)
for
{
peekData
,
peekErr
:=
peekBuffer
.
ReadBytes
(
'\n'
)
if
peekErr
!=
nil
&&
peekErr
!=
io
.
EOF
{
p
.
debug
(
"readPythonMultilines: failed to peek with error: %v"
,
peekErr
)
return
""
,
peekErr
}
p
.
debug
(
"readPythonMultilines: parsing %q"
,
string
(
peekData
))
peekMatches
:=
pythonMultiline
.
FindStringSubmatch
(
string
(
peekData
))
p
.
debug
(
"readPythonMultilines: matched %d parts"
,
len
(
peekMatches
))
for
n
,
v
:=
range
peekMatches
{
p
.
debug
(
" %d: %q"
,
n
,
v
)
}
// Return if not a Python multiline value.
if
len
(
peekMatches
)
!=
3
{
p
.
debug
(
"readPythonMultilines: end of value, got: %q"
,
line
)
return
line
,
nil
}
// Advance the parser reader (buffer) in-sync with the peek buffer.
_
,
err
:=
p
.
buf
.
Discard
(
len
(
peekData
))
if
err
!=
nil
{
p
.
debug
(
"readPythonMultilines: failed to skip to the end, returning error"
)
return
""
,
err
}
line
+=
"
\n
"
+
peekMatches
[
0
]
}
}
// parse parses data through an io.Reader.
func
(
f
*
File
)
parse
(
reader
io
.
Reader
)
(
err
error
)
{
p
:=
newParser
(
reader
,
parserOptions
{
IgnoreContinuation
:
f
.
options
.
IgnoreContinuation
,
IgnoreInlineComment
:
f
.
options
.
IgnoreInlineComment
,
AllowPythonMultilineValues
:
f
.
options
.
AllowPythonMultilineValues
,
SpaceBeforeInlineComment
:
f
.
options
.
SpaceBeforeInlineComment
,
UnescapeValueDoubleQuotes
:
f
.
options
.
UnescapeValueDoubleQuotes
,
UnescapeValueCommentSymbols
:
f
.
options
.
UnescapeValueCommentSymbols
,
PreserveSurroundedQuote
:
f
.
options
.
PreserveSurroundedQuote
,
DebugFunc
:
f
.
options
.
DebugFunc
,
ReaderBufferSize
:
f
.
options
.
ReaderBufferSize
,
})
if
err
=
p
.
BOM
();
err
!=
nil
{
return
fmt
.
Errorf
(
"BOM: %v"
,
err
)
}
// Ignore error because default section name is never empty string.
name
:=
DefaultSection
if
f
.
options
.
Insensitive
||
f
.
options
.
InsensitiveSections
{
name
=
strings
.
ToLower
(
DefaultSection
)
}
section
,
_
:=
f
.
NewSection
(
name
)
// This "last" is not strictly equivalent to "previous one" if current key is not the first nested key
var
isLastValueEmpty
bool
var
lastRegularKey
*
Key
var
line
[]
byte
var
inUnparseableSection
bool
// NOTE: Iterate and increase `currentPeekSize` until
// the size of the parser buffer is found.
// TODO(unknwon): When Golang 1.10 is the lowest version supported, replace with `parserBufferSize := p.buf.Size()`.
parserBufferSize
:=
0
// NOTE: Peek 4kb at a time.
currentPeekSize
:=
minReaderBufferSize
if
f
.
options
.
AllowPythonMultilineValues
{
for
{
peekBytes
,
_
:=
p
.
buf
.
Peek
(
currentPeekSize
)
peekBytesLength
:=
len
(
peekBytes
)
if
parserBufferSize
>=
peekBytesLength
{
break
}
currentPeekSize
*=
2
parserBufferSize
=
peekBytesLength
}
}
for
!
p
.
isEOF
{
line
,
err
=
p
.
readUntil
(
'\n'
)
if
err
!=
nil
{
return
err
}
if
f
.
options
.
AllowNestedValues
&&
isLastValueEmpty
&&
len
(
line
)
>
0
{
if
line
[
0
]
==
' '
||
line
[
0
]
==
'\t'
{
err
=
lastRegularKey
.
addNestedValue
(
string
(
bytes
.
TrimSpace
(
line
)))
if
err
!=
nil
{
return
err
}
continue
}
}
line
=
bytes
.
TrimLeftFunc
(
line
,
unicode
.
IsSpace
)
if
len
(
line
)
==
0
{
continue
}
// Comments
if
line
[
0
]
==
'#'
||
line
[
0
]
==
';'
{
// Note: we do not care ending line break,
// it is needed for adding second line,
// so just clean it once at the end when set to value.
p
.
comment
.
Write
(
line
)
continue
}
// Section
if
line
[
0
]
==
'['
{
// Read to the next ']' (TODO: support quoted strings)
closeIdx
:=
bytes
.
LastIndexByte
(
line
,
']'
)
if
closeIdx
==
-
1
{
return
fmt
.
Errorf
(
"unclosed section: %s"
,
line
)
}
name
:=
string
(
line
[
1
:
closeIdx
])
section
,
err
=
f
.
NewSection
(
name
)
if
err
!=
nil
{
return
err
}
comment
,
has
:=
cleanComment
(
line
[
closeIdx
+
1
:
])
if
has
{
p
.
comment
.
Write
(
comment
)
}
section
.
Comment
=
strings
.
TrimSpace
(
p
.
comment
.
String
())
// Reset auto-counter and comments
p
.
comment
.
Reset
()
p
.
count
=
1
// Nested values can't span sections
isLastValueEmpty
=
false
inUnparseableSection
=
false
for
i
:=
range
f
.
options
.
UnparseableSections
{
if
f
.
options
.
UnparseableSections
[
i
]
==
name
||
((
f
.
options
.
Insensitive
||
f
.
options
.
InsensitiveSections
)
&&
strings
.
EqualFold
(
f
.
options
.
UnparseableSections
[
i
],
name
))
{
inUnparseableSection
=
true
continue
}
}
continue
}
if
inUnparseableSection
{
section
.
isRawSection
=
true
section
.
rawBody
+=
string
(
line
)
continue
}
kname
,
offset
,
err
:=
readKeyName
(
f
.
options
.
KeyValueDelimiters
,
line
)
if
err
!=
nil
{
switch
{
// Treat as boolean key when desired, and whole line is key name.
case
IsErrDelimiterNotFound
(
err
)
:
switch
{
case
f
.
options
.
AllowBooleanKeys
:
kname
,
err
:=
p
.
readValue
(
line
,
parserBufferSize
)
if
err
!=
nil
{
return
err
}
key
,
err
:=
section
.
NewBooleanKey
(
kname
)
if
err
!=
nil
{
return
err
}
key
.
Comment
=
strings
.
TrimSpace
(
p
.
comment
.
String
())
p
.
comment
.
Reset
()
continue
case
f
.
options
.
SkipUnrecognizableLines
:
continue
}
case
IsErrEmptyKeyName
(
err
)
&&
f
.
options
.
SkipUnrecognizableLines
:
continue
}
return
err
}
// Auto increment.
isAutoIncr
:=
false
if
kname
==
"-"
{
isAutoIncr
=
true
kname
=
"#"
+
strconv
.
Itoa
(
p
.
count
)
p
.
count
++
}
value
,
err
:=
p
.
readValue
(
line
[
offset
:
],
parserBufferSize
)
if
err
!=
nil
{
return
err
}
isLastValueEmpty
=
len
(
value
)
==
0
key
,
err
:=
section
.
NewKey
(
kname
,
value
)
if
err
!=
nil
{
return
err
}
key
.
isAutoIncrement
=
isAutoIncr
key
.
Comment
=
strings
.
TrimSpace
(
p
.
comment
.
String
())
p
.
comment
.
Reset
()
lastRegularKey
=
key
}
return
nil
}
vendor/gopkg.in/ini.v1/section.go
0 → 100644
View file @
ae831b78
// Copyright 2014 Unknwon
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
package
ini
import
(
"errors"
"fmt"
"strings"
)
// Section represents a config section.
type
Section
struct
{
f
*
File
Comment
string
name
string
keys
map
[
string
]
*
Key
keyList
[]
string
keysHash
map
[
string
]
string
isRawSection
bool
rawBody
string
}
func
newSection
(
f
*
File
,
name
string
)
*
Section
{
return
&
Section
{
f
:
f
,
name
:
name
,
keys
:
make
(
map
[
string
]
*
Key
),
keyList
:
make
([]
string
,
0
,
10
),
keysHash
:
make
(
map
[
string
]
string
),
}
}
// Name returns name of Section.
func
(
s
*
Section
)
Name
()
string
{
return
s
.
name
}
// Body returns rawBody of Section if the section was marked as unparseable.
// It still follows the other rules of the INI format surrounding leading/trailing whitespace.
func
(
s
*
Section
)
Body
()
string
{
return
strings
.
TrimSpace
(
s
.
rawBody
)
}
// SetBody updates body content only if section is raw.
func
(
s
*
Section
)
SetBody
(
body
string
)
{
if
!
s
.
isRawSection
{
return
}
s
.
rawBody
=
body
}
// NewKey creates a new key to given section.
func
(
s
*
Section
)
NewKey
(
name
,
val
string
)
(
*
Key
,
error
)
{
if
len
(
name
)
==
0
{
return
nil
,
errors
.
New
(
"error creating new key: empty key name"
)
}
else
if
s
.
f
.
options
.
Insensitive
||
s
.
f
.
options
.
InsensitiveKeys
{
name
=
strings
.
ToLower
(
name
)
}
if
s
.
f
.
BlockMode
{
s
.
f
.
lock
.
Lock
()
defer
s
.
f
.
lock
.
Unlock
()
}
if
inSlice
(
name
,
s
.
keyList
)
{
if
s
.
f
.
options
.
AllowShadows
{
if
err
:=
s
.
keys
[
name
]
.
addShadow
(
val
);
err
!=
nil
{
return
nil
,
err
}
}
else
{
s
.
keys
[
name
]
.
value
=
val
s
.
keysHash
[
name
]
=
val
}
return
s
.
keys
[
name
],
nil
}
s
.
keyList
=
append
(
s
.
keyList
,
name
)
s
.
keys
[
name
]
=
newKey
(
s
,
name
,
val
)
s
.
keysHash
[
name
]
=
val
return
s
.
keys
[
name
],
nil
}
// NewBooleanKey creates a new boolean type key to given section.
func
(
s
*
Section
)
NewBooleanKey
(
name
string
)
(
*
Key
,
error
)
{
key
,
err
:=
s
.
NewKey
(
name
,
"true"
)
if
err
!=
nil
{
return
nil
,
err
}
key
.
isBooleanType
=
true
return
key
,
nil
}
// GetKey returns key in section by given name.
func
(
s
*
Section
)
GetKey
(
name
string
)
(
*
Key
,
error
)
{
if
s
.
f
.
BlockMode
{
s
.
f
.
lock
.
RLock
()
}
if
s
.
f
.
options
.
Insensitive
||
s
.
f
.
options
.
InsensitiveKeys
{
name
=
strings
.
ToLower
(
name
)
}
key
:=
s
.
keys
[
name
]
if
s
.
f
.
BlockMode
{
s
.
f
.
lock
.
RUnlock
()
}
if
key
==
nil
{
// Check if it is a child-section.
sname
:=
s
.
name
for
{
if
i
:=
strings
.
LastIndex
(
sname
,
s
.
f
.
options
.
ChildSectionDelimiter
);
i
>
-
1
{
sname
=
sname
[
:
i
]
sec
,
err
:=
s
.
f
.
GetSection
(
sname
)
if
err
!=
nil
{
continue
}
return
sec
.
GetKey
(
name
)
}
break
}
return
nil
,
fmt
.
Errorf
(
"error when getting key of section %q: key %q not exists"
,
s
.
name
,
name
)
}
return
key
,
nil
}
// HasKey returns true if section contains a key with given name.
func
(
s
*
Section
)
HasKey
(
name
string
)
bool
{
key
,
_
:=
s
.
GetKey
(
name
)
return
key
!=
nil
}
// Deprecated: Use "HasKey" instead.
func
(
s
*
Section
)
Haskey
(
name
string
)
bool
{
return
s
.
HasKey
(
name
)
}
// HasValue returns true if section contains given raw value.
func
(
s
*
Section
)
HasValue
(
value
string
)
bool
{
if
s
.
f
.
BlockMode
{
s
.
f
.
lock
.
RLock
()
defer
s
.
f
.
lock
.
RUnlock
()
}
for
_
,
k
:=
range
s
.
keys
{
if
value
==
k
.
value
{
return
true
}
}
return
false
}
// Key assumes named Key exists in section and returns a zero-value when not.
func
(
s
*
Section
)
Key
(
name
string
)
*
Key
{
key
,
err
:=
s
.
GetKey
(
name
)
if
err
!=
nil
{
// It's OK here because the only possible error is empty key name,
// but if it's empty, this piece of code won't be executed.
key
,
_
=
s
.
NewKey
(
name
,
""
)
return
key
}
return
key
}
// Keys returns list of keys of section.
func
(
s
*
Section
)
Keys
()
[]
*
Key
{
keys
:=
make
([]
*
Key
,
len
(
s
.
keyList
))
for
i
:=
range
s
.
keyList
{
keys
[
i
]
=
s
.
Key
(
s
.
keyList
[
i
])
}
return
keys
}
// ParentKeys returns list of keys of parent section.
func
(
s
*
Section
)
ParentKeys
()
[]
*
Key
{
var
parentKeys
[]
*
Key
sname
:=
s
.
name
for
{
if
i
:=
strings
.
LastIndex
(
sname
,
s
.
f
.
options
.
ChildSectionDelimiter
);
i
>
-
1
{
sname
=
sname
[
:
i
]
sec
,
err
:=
s
.
f
.
GetSection
(
sname
)
if
err
!=
nil
{
continue
}
parentKeys
=
append
(
parentKeys
,
sec
.
Keys
()
...
)
}
else
{
break
}
}
return
parentKeys
}
// KeyStrings returns list of key names of section.
func
(
s
*
Section
)
KeyStrings
()
[]
string
{
list
:=
make
([]
string
,
len
(
s
.
keyList
))
copy
(
list
,
s
.
keyList
)
return
list
}
// KeysHash returns keys hash consisting of names and values.
func
(
s
*
Section
)
KeysHash
()
map
[
string
]
string
{
if
s
.
f
.
BlockMode
{
s
.
f
.
lock
.
RLock
()
defer
s
.
f
.
lock
.
RUnlock
()
}
hash
:=
make
(
map
[
string
]
string
,
len
(
s
.
keysHash
))
for
key
,
value
:=
range
s
.
keysHash
{
hash
[
key
]
=
value
}
return
hash
}
// DeleteKey deletes a key from section.
func
(
s
*
Section
)
DeleteKey
(
name
string
)
{
if
s
.
f
.
BlockMode
{
s
.
f
.
lock
.
Lock
()
defer
s
.
f
.
lock
.
Unlock
()
}
for
i
,
k
:=
range
s
.
keyList
{
if
k
==
name
{
s
.
keyList
=
append
(
s
.
keyList
[
:
i
],
s
.
keyList
[
i
+
1
:
]
...
)
delete
(
s
.
keys
,
name
)
delete
(
s
.
keysHash
,
name
)
return
}
}
}
// ChildSections returns a list of child sections of current section.
// For example, "[parent.child1]" and "[parent.child12]" are child sections
// of section "[parent]".
func
(
s
*
Section
)
ChildSections
()
[]
*
Section
{
prefix
:=
s
.
name
+
s
.
f
.
options
.
ChildSectionDelimiter
children
:=
make
([]
*
Section
,
0
,
3
)
for
_
,
name
:=
range
s
.
f
.
sectionList
{
if
strings
.
HasPrefix
(
name
,
prefix
)
{
children
=
append
(
children
,
s
.
f
.
sections
[
name
]
...
)
}
}
return
children
}
vendor/gopkg.in/ini.v1/struct.go
0 → 100644
View file @
ae831b78
This diff is collapsed.
Click to expand it.
vendor/modules.txt
View file @
ae831b78
...
...
@@ -38,6 +38,9 @@ golang.org/x/mod/semver
## explicit; go 1.18
golang.org/x/sys/unix
golang.org/x/sys/windows
# gopkg.in/ini.v1 v1.67.0
## explicit
gopkg.in/ini.v1
# sigs.k8s.io/yaml v1.4.0
## explicit; go 1.12
sigs.k8s.io/yaml
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment