Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
c258e6096f | |||
a5976526ae | |||
3d467bd979 | |||
28fe0bda17 | |||
25f6b1537d | |||
287547b69e | |||
f4934225b6 | |||
69be8312f8 | |||
f083dcd3d8 | |||
44e955a047 | |||
c76140ffe1 | |||
a89e63f19f | |||
0ea49ff1ad | |||
325c6c25d7 |
118
.github/workflows/binary-release.yml
vendored
Normal file
118
.github/workflows/binary-release.yml
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
name: binary release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '[0-9]+.[0-9]+.[0-9]+'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Get the version
|
||||
id: get_version
|
||||
run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.13.0'
|
||||
|
||||
- name: Build
|
||||
run: make -j $(nproc) compile VERSION=${{ steps.get_version.outputs.VERSION }}
|
||||
|
||||
- name: create release
|
||||
id: create_release
|
||||
uses: actions/create-release@latest
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ steps.get_version.outputs.VERSION }}
|
||||
release_name: Release ${{ steps.get_version.outputs.VERSION }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
- name: darwin-386
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./bin/${{ github.event.repository.name }}-darwin-386
|
||||
asset_name: ${{ github.event.repository.name }}-darwin-386
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: darwin-amd64
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./bin/${{ github.event.repository.name }}-darwin-amd64
|
||||
asset_name: ${{ github.event.repository.name }}-darwin-amd64
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: freebsd-386
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./bin/${{ github.event.repository.name }}-freebsd-386
|
||||
asset_name: ${{ github.event.repository.name }}-freebsd-386
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: freebsd-amd64
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./bin/${{ github.event.repository.name }}-freebsd-amd64
|
||||
asset_name: ${{ github.event.repository.name }}-freebsd-amd64
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: linux-386
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./bin/${{ github.event.repository.name }}-linux-386
|
||||
asset_name: ${{ github.event.repository.name }}-linux-386
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: linux-amd64
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./bin/${{ github.event.repository.name }}-linux-amd64
|
||||
asset_name: ${{ github.event.repository.name }}-linux-amd64
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: windows-386
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./bin/${{ github.event.repository.name }}-windows-386.exe
|
||||
asset_name: ${{ github.event.repository.name }}-windows-386.exe
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: windows-amd64
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./bin/${{ github.event.repository.name }}-windows-amd64.exe
|
||||
asset_name: ${{ github.event.repository.name }}-windows-amd64.exe
|
||||
asset_content_type: application/octet-stream
|
||||
|
23
.github/workflows/build.yml
vendored
Normal file
23
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: '1.13.0'
|
||||
|
||||
- name: Build
|
||||
run: make -j $(nproc)
|
||||
|
23
.gitignore
vendored
23
.gitignore
vendored
@ -1,20 +1,3 @@
|
||||
# Binaries for programs and plugins
|
||||
bin/*
|
||||
multini
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Custom binary test
|
||||
tests/out_ini/*
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
/bin/
|
||||
/test/data/out_ini/
|
||||
/cmd/multini/multini
|
||||
|
36
Makefile
36
Makefile
@ -1,21 +1,30 @@
|
||||
NAME=multini
|
||||
VERSION=0.2
|
||||
GOCMD=go
|
||||
LDFLAGS:="$(LDFLAGS) -X 'main.Version=$(VERSION)'"
|
||||
GOBUILD=$(GOCMD) build -ldflags=$(LDFLAGS)
|
||||
SRCMAIN=.
|
||||
BINDIR=bin
|
||||
BIN=$(BINDIR)/$(NAME)
|
||||
README=README
|
||||
LICENSE=LICENSE
|
||||
TEST=./run_test.sh
|
||||
PREFIX=/usr
|
||||
NAME = multini
|
||||
VERSION = dev_$(shell date +%F_%T)
|
||||
GOCMD = go
|
||||
LDFLAGS := "$(LDFLAGS) -X 'main.Version=$(VERSION)'"
|
||||
GOBUILD = $(GOCMD) build -ldflags=$(LDFLAGS)
|
||||
SRCMAIN = ./cmd/$(NAME)
|
||||
SRCDOC = ./doc
|
||||
SRCTEST = ./test
|
||||
BINDIR = bin
|
||||
BIN = $(BINDIR)/$(NAME)
|
||||
README = $(SRCDOC)/README
|
||||
LICENSE = LICENSE
|
||||
TEST = $(SRCTEST)/run_test.sh
|
||||
PREFIX = /usr
|
||||
|
||||
.PHONY: all prep doc build check-build freebsd-386 darwin-386 linux-386 windows-386 freebsd-amd64 darwin-amd64 linux-amd64 windows-amd64 compile install check-install uninstall clean test
|
||||
|
||||
all: build
|
||||
|
||||
prep: clean
|
||||
go mod init; go mod tidy
|
||||
mkdir $(BINDIR)
|
||||
|
||||
doc: check-build
|
||||
test -d $(SRCDOC) || mkdir $(SRCDOC)
|
||||
$(BIN) --help > $(README)
|
||||
|
||||
build: prep
|
||||
$(GOBUILD) -o $(BIN) $(SRCMAIN)
|
||||
|
||||
@ -48,7 +57,7 @@ windows-amd64: prep
|
||||
|
||||
compile: freebsd-386 darwin-386 linux-386 windows-386 freebsd-amd64 darwin-amd64 linux-amd64 windows-amd64
|
||||
|
||||
install: check-build
|
||||
install: check-build doc
|
||||
install -m 755 -d $(PREFIX)/bin/
|
||||
install -m 755 $(BIN) $(PREFIX)/bin/
|
||||
install -m 755 -d $(PREFIX)/share/licenses/$(NAME)/
|
||||
@ -71,3 +80,4 @@ clean:
|
||||
|
||||
test: check-build
|
||||
$(TEST) $(BIN)
|
||||
|
||||
|
2
README.md
Normal file
2
README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# multini
|
||||
it's like crudini but for ini files with duplicate parameter names
|
@ -1,8 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"multini/output"
|
||||
"multini/types"
|
||||
"multini/internal/output"
|
||||
"multini/internal/types"
|
||||
)
|
||||
|
||||
func chk() int {
|
@ -4,8 +4,8 @@ import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"multini/output"
|
||||
"multini/types"
|
||||
"multini/internal/output"
|
||||
"multini/internal/types"
|
||||
|
||||
"github.com/juju/gnuflag"
|
||||
)
|
||||
@ -100,7 +100,7 @@ func init() {
|
||||
}
|
||||
|
||||
func parseArgs() error {
|
||||
gnuflag.Parse(true)
|
||||
gnuflag.Parse(false)
|
||||
|
||||
// info
|
||||
switch {
|
@ -3,8 +3,8 @@ package main
|
||||
import (
|
||||
"os"
|
||||
|
||||
"multini/output"
|
||||
"multini/types"
|
||||
"multini/internal/output"
|
||||
"multini/internal/types"
|
||||
)
|
||||
|
||||
const (
|
@ -7,49 +7,103 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"multini/output"
|
||||
"multini/types"
|
||||
"multini/internal/output"
|
||||
"multini/internal/types"
|
||||
)
|
||||
|
||||
var (
|
||||
// Ng - Named Group
|
||||
NgPrefix string = `prefix`
|
||||
NgPostifx string = `postfix`
|
||||
NgSection string = `section`
|
||||
NgKey string = `key`
|
||||
NgKeyPostfix string = `key_postfix`
|
||||
NgValue string = `value`
|
||||
NgValuePrefix string = `value_prefix`
|
||||
NgValuePostfix string = `value_postfix`
|
||||
NgComment string = `comment`
|
||||
NgCommentPrefix string = `comment_prefix`
|
||||
NgPrefix string = `prefix`
|
||||
NgPostifx string = `postfix`
|
||||
NgSection string = `section`
|
||||
NgKey string = `key`
|
||||
NgKeyPostfix string = `key_postfix`
|
||||
NgValue string = `value`
|
||||
NgValuePrefix string = `value_prefix`
|
||||
NgValuePostfix string = `value_postfix`
|
||||
NgComment string = `comment`
|
||||
NgData string = `data`
|
||||
|
||||
RxBodyPrefix string = `(?P<` + NgPrefix + `>\s+)?`
|
||||
RxSectionName string = `\[(?P<` + NgSection + `>.+)\]`
|
||||
RxKey string = `(?P<` + NgKey + `>(?:[^;#=]+[^\s=;#]|[^;#=]))?`
|
||||
RxKeyPostfix string = `(?P<` + NgKeyPostfix + `>\s+)?`
|
||||
RxValuePrefix string = `(?P<` + NgValuePrefix + `>\s+)?`
|
||||
RxValue string = `(?P<` + NgValue + `>(?:[^;#]+[^\s;#]|[^;#]))?`
|
||||
RxValuePostfix string = `(?P<` + NgValuePostfix + `>\s+)?`
|
||||
RxKeyVal string = RxKey + RxKeyPostfix + `=` + RxValuePrefix + RxValue + RxValuePostfix
|
||||
RxBody string = `(?:` + RxSectionName + `|` + RxKeyVal + `)?`
|
||||
RxBodyPostfix string = `(?P<` + NgPostifx + `>\s+)?`
|
||||
RxCommentPrefix string = `(?P<` + NgCommentPrefix + `>[#;]\s*)`
|
||||
RxCommentText string = `(?P<` + NgComment + `>.+)?`
|
||||
RxComment string = `(?:` + RxCommentPrefix + RxCommentText + `)?`
|
||||
Rx string = RxBodyPrefix + RxBody + RxBodyPostfix + RxComment
|
||||
RxCompiled *regexp.Regexp = regexp.MustCompile(Rx)
|
||||
RxEmpty string = `^(?P<` + NgPrefix + `>\s+)?$`
|
||||
RxSection string = `^(?P<` + NgPrefix + `>\s+)?\[(?P<` + NgSection + `>[^\]]+)\](?P<` + NgPostifx + `>\s+)?$`
|
||||
RxKey string = `^(?P<` + NgPrefix + `>\s+)?(?P<` + NgKey + `>.*[^\s]+)(?P<` + NgKeyPostfix + `>\s+)?$`
|
||||
RxValue string = `^(?P<` + NgValuePrefix + `>\s+)?(?P<` + NgValue + `>.*[^\s])(?P<` + NgValuePostfix + `>\s+)?$`
|
||||
|
||||
RxEmptyCompile *regexp.Regexp = regexp.MustCompile(RxEmpty)
|
||||
RxSectionCompile *regexp.Regexp = regexp.MustCompile(RxSection)
|
||||
RxKeyCompile *regexp.Regexp = regexp.MustCompile(RxKey)
|
||||
RxValueCompile *regexp.Regexp = regexp.MustCompile(RxValue)
|
||||
)
|
||||
|
||||
func rxParse(rx *regexp.Regexp, str string) map[string]string {
|
||||
match := rx.FindStringSubmatch(str)
|
||||
result := make(map[string]string)
|
||||
for i, name := range rx.SubexpNames() {
|
||||
func parse(str string) map[string]string {
|
||||
var result map[string]string = make(map[string]string)
|
||||
var data string
|
||||
|
||||
data, result[NgComment] = getDataComment(str)
|
||||
|
||||
if data != "" {
|
||||
findNamedGroups(data, RxEmptyCompile, &result)
|
||||
}
|
||||
|
||||
if result[NgPrefix] != "" {
|
||||
return result
|
||||
}
|
||||
|
||||
findNamedGroups(data, RxSectionCompile, &result)
|
||||
|
||||
if result[NgSection] == "" && data != "" {
|
||||
keyPart, valPart := getKeyValue(data)
|
||||
findNamedGroups(keyPart, RxKeyCompile, &result)
|
||||
findNamedGroups(valPart, RxValueCompile, &result)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func findNamedGroups(str string, Rx *regexp.Regexp, result *map[string]string) {
|
||||
match := Rx.FindStringSubmatch(str)
|
||||
for i, name := range Rx.SubexpNames() {
|
||||
if i != 0 && name != "" && i <= len(match) {
|
||||
result[name] = match[i]
|
||||
(*result)[name] = match[i]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func getDataComment(str string) (string, string) {
|
||||
var indexes []int
|
||||
var commentIndex int = -1
|
||||
|
||||
indexes = append(indexes, strings.Index(str, "//"))
|
||||
indexes = append(indexes, strings.Index(str, "#"))
|
||||
indexes = append(indexes, strings.Index(str, ";"))
|
||||
|
||||
for _, index := range indexes {
|
||||
if commentIndex == -1 {
|
||||
if index != -1 {
|
||||
commentIndex = index
|
||||
}
|
||||
} else {
|
||||
if index != -1 {
|
||||
if commentIndex > index {
|
||||
commentIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if commentIndex == -1 {
|
||||
return str, ""
|
||||
} else {
|
||||
return str[:commentIndex], str[commentIndex:]
|
||||
}
|
||||
}
|
||||
|
||||
func getKeyValue(data string) (string, string) {
|
||||
index := strings.Index(data, "=")
|
||||
if index != -1 {
|
||||
return data[:index], data[index+1:]
|
||||
}
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func debugMap(el map[string]string) string {
|
||||
@ -61,14 +115,14 @@ func debugMap(el map[string]string) string {
|
||||
}
|
||||
|
||||
func appendLine(ini *types.Ini, line string) error {
|
||||
elements := rxParse(RxCompiled, line)
|
||||
// elements := rxParse(line)
|
||||
elements := parse(line)
|
||||
switch {
|
||||
case elements[NgSection] != "":
|
||||
var newSection types.Section
|
||||
newSection.Name = elements[NgSection]
|
||||
newSection.Prefix = elements[NgPrefix]
|
||||
newSection.Postfix = elements[NgPostifx]
|
||||
newSection.Comment.Prefix = elements[NgCommentPrefix]
|
||||
newSection.Comment.Value = elements[NgComment]
|
||||
if newSection.Line() == line {
|
||||
ini.Sections = append(ini.Sections, &newSection)
|
||||
@ -87,7 +141,6 @@ func appendLine(ini *types.Ini, line string) error {
|
||||
newKeyValue.PrefixValue = elements[NgValuePrefix]
|
||||
newKeyValue.PostfixValue = elements[NgValuePostfix]
|
||||
newKeyValue.Comment.Value = elements[NgComment]
|
||||
newKeyValue.Comment.Prefix = elements[NgCommentPrefix]
|
||||
if newKeyValue.Line() == line {
|
||||
ini.Sections[len(ini.Sections)-1].(*types.Section).Lines = append(ini.Sections[len(ini.Sections)-1].(*types.Section).Lines, &newKeyValue)
|
||||
return nil
|
||||
@ -98,8 +151,8 @@ func appendLine(ini *types.Ini, line string) error {
|
||||
}
|
||||
case elements[NgComment] != "":
|
||||
var newComment types.Comment
|
||||
newComment.Prefix = elements[NgPrefix] + elements[NgCommentPrefix]
|
||||
newComment.Value = elements[NgComment]
|
||||
newComment.Prefix = elements[NgPrefix]
|
||||
if newComment.Line() == line {
|
||||
ini.Sections[len(ini.Sections)-1].(*types.Section).Lines = append(ini.Sections[len(ini.Sections)-1].(*types.Section).Lines, &newComment)
|
||||
return nil
|
@ -2,13 +2,55 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"multini/types"
|
||||
"multini/internal/types"
|
||||
)
|
||||
|
||||
// Source: https://gist.github.com/var23rav/23ae5d0d4d830aff886c3c970b8f6c6b
|
||||
/*
|
||||
GoLang: os.Rename() give error "invalid cross-device link" for Docker container with Volumes.
|
||||
MoveFile(source, destination) will work moving file between folders
|
||||
*/
|
||||
func tryMoveFile(sourcePath, destPath string) error {
|
||||
inputFile, err := os.Open(sourcePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
outputFile, err := os.Create(destPath)
|
||||
if err != nil {
|
||||
inputFile.Close()
|
||||
return err
|
||||
}
|
||||
defer outputFile.Close()
|
||||
_, err = io.Copy(outputFile, inputFile)
|
||||
inputFile.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// The copy was successful, so now delete the original file
|
||||
err = os.Remove(sourcePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func tryRemoveRenameFile(sourcePath, destPath string) bool {
|
||||
err := os.Remove(destPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
err = os.Rename(sourcePath, destPath)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func replaceOriginal(oldFile, newFile string) error {
|
||||
realOldFile, err := filepath.EvalSymlinks(oldFile)
|
||||
if err != nil {
|
||||
@ -23,14 +65,11 @@ func replaceOriginal(oldFile, newFile string) error {
|
||||
|
||||
var uid, gid int = GetUidGid(infoOldFile)
|
||||
|
||||
err = os.Remove(realOldFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = os.Rename(newFile, realOldFile)
|
||||
if err != nil {
|
||||
return err
|
||||
if !tryRemoveRenameFile(newFile, realOldFile) {
|
||||
err = tryMoveFile(newFile, realOldFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = os.Chmod(realOldFile, mode)
|
||||
@ -75,7 +114,7 @@ func iniWriteInplace(filename string, ini *types.Ini) error {
|
||||
}
|
||||
mode = info.Mode()
|
||||
}
|
||||
targetFile, err := os.OpenFile(realfilename, os.O_WRONLY|os.O_CREATE, mode)
|
||||
targetFile, err := os.OpenFile(realfilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode)
|
||||
if err == nil {
|
||||
datawriter := bufio.NewWriter(targetFile)
|
||||
_, err = datawriter.WriteString(ini.Full())
|
5
go.mod
Normal file
5
go.mod
Normal file
@ -0,0 +1,5 @@
|
||||
module multini
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
||||
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d h1:c93kUJDtVAXFEhsCh5jSxyOJmFHuzcihnslQiX8Urwo=
|
||||
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
|
@ -89,6 +89,14 @@ func (obj *Ini) GetKeyVal(section, key, value string) error {
|
||||
func (obj *Ini) AddSection(section string) *Section {
|
||||
sect, err := obj.FindSection(section)
|
||||
if err != nil {
|
||||
sectSize := len(obj.Sections)
|
||||
if sectSize > 1 {
|
||||
prevSect := obj.Sections[sectSize-1].(*Section)
|
||||
lineSize := len(prevSect.Lines)
|
||||
if lineSize == 0 || lineSize > 0 && prevSect.Lines[lineSize-1].Type() != TEmptyLine {
|
||||
obj.Sections[sectSize-1].(*Section).Lines = append(obj.Sections[sectSize-1].(*Section).Lines, &EmptyLine{})
|
||||
}
|
||||
}
|
||||
var newSection Section
|
||||
newSection.Name = section
|
||||
newSection.Prefix = obj.Sections[len(obj.Sections)-1].Indent()
|
@ -1,6 +1,6 @@
|
||||
# comment
|
||||
; comment again
|
||||
|
||||
// comment with indent
|
||||
DefKey1 = Some Value1
|
||||
DefKey2 = Some Value2 And Tabs! # With Comment
|
||||
DefKey3=NoSpaces!
|
||||
@ -10,7 +10,7 @@ DefKey3=NoSpaces!
|
||||
Key2 = 2
|
||||
Key3 = 3
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
||||
@ -17,4 +17,5 @@ DefKey3=NoSpaces!
|
||||
[SectionWithIndent]
|
||||
Key=Value
|
||||
[SectionWithoutNewLineBefore]
|
||||
|
||||
[NewSection]
|
@ -8,7 +8,7 @@ DefKey3=NoSpaces!
|
||||
[SimpleSection] # Comment For Section
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
|
||||
[SectionWithIndent]
|
||||
Key=Value
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 3
|
||||
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
1
test/data/expected_ini/test_get_key_slashes.sh.ini
Normal file
1
test/data/expected_ini/test_get_key_slashes.sh.ini
Normal file
@ -0,0 +1 @@
|
||||
skip/skip
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = onlyone
|
||||
|
||||
[SectionWithIndent]
|
@ -1,6 +1,6 @@
|
||||
# comment
|
||||
; comment again
|
||||
|
||||
// comment with indent
|
||||
DefKey1 = Some Value1
|
||||
DefKey2 = Some Value2 And Tabs! # With Comment
|
||||
DefKey3=NoSpaces!
|
||||
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
19
test/data/in_ini/test_get_key_slashes.sh.ini
Normal file
19
test/data/in_ini/test_get_key_slashes.sh.ini
Normal file
@ -0,0 +1,19 @@
|
||||
# comment
|
||||
; comment again
|
||||
|
||||
DefKey1 = Some Value1
|
||||
DefKey2 = Some Value2 And Tabs! # With Comment
|
||||
DefKey3=NoSpaces!
|
||||
|
||||
[Slashes/Test] // Comment For Section
|
||||
./Dir1/File = skip/skip // comment
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
||||
|
||||
[SectionWithIndent]
|
||||
Key=Value
|
||||
[SectionWithoutNewLineBefore]
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
@ -9,7 +9,7 @@ DefKey3=NoSpaces!
|
||||
Key1 = 1
|
||||
Key2 = 2
|
||||
|
||||
[MultipleKeySection]
|
||||
[MultipleKeySection] // C style comment
|
||||
Key = 1
|
||||
Key = 2
|
||||
Key = 3
|
7
test/data/test_get_key_slashes.sh
Executable file
7
test/data/test_get_key_slashes.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
source "common.sh"
|
||||
|
||||
$Multini --get "$InIni" 'Slashes/Test' './Dir1/File' > "$OutIni"
|
||||
|
||||
compare
|
@ -1,10 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
DEF='\e[0m'; BLD='\e[1m'; RED='\e[31m'; GRN='\e[32m'; WHT='\e[97m'
|
||||
|
||||
ScriptFullname=$(readlink -e "$0")
|
||||
ScriptName=$(echo "$ScriptFullname" | awk -F '/' '{print $NF;}')
|
||||
ScriptDir=$(dirname "$ScriptFullname")
|
||||
TestDir="$ScriptDir/tests"
|
||||
TestDir="$ScriptDir/data"
|
||||
Multini=$(readlink -e "$1")
|
||||
|
||||
if [[ -z "$Multini" ]]; then
|
Reference in New Issue
Block a user