Skip to content

Commit

Permalink
feat: handle content and lines differently (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
femnad authored Jun 3, 2024
1 parent 19fe654 commit 58da75e
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 10 deletions.
3 changes: 2 additions & 1 deletion entity/ensurelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ type Replacement struct {
}

type LineInFile struct {
Content []string `yaml:"content"`
Content string `yaml:"content"`
File string `yaml:"file"`
Lines []string `yaml:"lines"`
Name string `yaml:"name"`
Replace []Replacement `yaml:"replace"`
RunAfter Step `yaml:"run_after"`
Expand Down
61 changes: 52 additions & 9 deletions provision/ensurelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"path"
"regexp"
"strings"

mapset "github.com/deckarep/golang-set/v2"

Expand All @@ -28,9 +29,9 @@ type ensureResult struct {
}

func ensure(file string, tmpFile *os.File, line entity.LineInFile) (result ensureResult, err error) {
content := mapset.NewSet[string]()
for _, l := range line.Content {
content.Add(l)
newLines := mapset.NewSet[string]()
for _, l := range line.Lines {
newLines.Add(l)
}

var newFile bool
Expand All @@ -42,29 +43,71 @@ func ensure(file string, tmpFile *os.File, line entity.LineInFile) (result ensur
}
defer srcFile.Close()

contentMatchProgress := false
contentPresent := false
contentLines := strings.Split(line.Content, "\n")
numContentLines := len(contentLines)

if !newFile {
scanner := bufio.NewScanner(srcFile)
var contentIdx int
var current string

var lineIdx int
for scanner.Scan() {
l := scanner.Text()
if content.Contains(l) {
content.Remove(l)
current = scanner.Text()

checkContent := !contentPresent
if contentMatchProgress || lineIdx == 0 {
checkContent = true
}
if checkContent {
if contentIdx < numContentLines && contentLines[contentIdx] == current {
contentMatchProgress = true
if contentIdx == numContentLines-1 {
contentPresent = true
}
contentIdx++
} else {
contentMatchProgress = false
contentIdx = 0
}
}

if newLines.Contains(current) {
newLines.Remove(current)
}
lineIdx++

_, err = tmpFile.WriteString(fmt.Sprintf("%s\n", current))
if err != nil {
return result, err
}
}

}

if content.Cardinality() == 0 {
if newLines.Cardinality() == 0 && contentPresent {
return
}

content.Each(func(l string) bool {
newLines.Each(func(l string) bool {
_, err = tmpFile.WriteString(fmt.Sprintf("%s\n", l))
return err != nil
})

if err != nil {
return result, fmt.Errorf("error ensuring lines in file %s", file)
}

if !contentPresent {
for _, l := range contentLines {
_, err = tmpFile.WriteString(fmt.Sprintf("%s\n", l))
if err != nil {
return result, fmt.Errorf("error ensuring content in file %s", file)
}
}
}

return ensureResult{changed: true, new: newFile}, nil
}

Expand Down
2 changes: 2 additions & 0 deletions tests/config/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ template:
- src: unattended-upgrades.conf
dest: /etc/apt/apt.conf.d/50unattended-upgrades
when: os "ubuntu"

line:
44 changes: 44 additions & 0 deletions tests/integration/lineinfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,21 @@ func TestLineInFile(t *testing.T) {
bazContent := `foo
bar
baz
`
contentFound := `exa
[default]
x=y
end
`
contentNotFound := `[default]
line
x=y
`
bazFile := fmt.Sprintf("%s/baz", testDir)
contentFoundFile := fmt.Sprintf("%s/fred", testDir)
contentNotFoundFile := fmt.Sprintf("%s/barney", testDir)

tests := []struct {
name string
Expand Down Expand Up @@ -168,6 +181,37 @@ nope
},
},
},
{
name: "Content already present",
files: map[string]string{
"fred": contentFound,
},
want: map[string]string{"fred": contentFound},
lineInFile: entity.LineInFile{
File: contentFoundFile,
Name: "ensure",
Content: `[default]
x=y`,
},
},
{
name: "Content not present",
files: map[string]string{
"barney": contentNotFound,
},
want: map[string]string{"barney": `[default]
line
x=y
[default]
x=y
`},
lineInFile: entity.LineInFile{
File: contentNotFoundFile,
Name: "ensure",
Content: `[default]
x=y`,
},
},
}

configFile := "lineinfile/fup.yml"
Expand Down

0 comments on commit 58da75e

Please sign in to comment.