From 6abc66c68e4de56aad289dc3134dde5827de1c73 Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Sun, 30 Jun 2024 15:07:42 +0200 Subject: [PATCH] fix: exluding now work properly --- source/html/sync.go | 231 +++++++++++++++++++---------- source/types/sync-specification.go | 14 +- 2 files changed, 160 insertions(+), 85 deletions(-) diff --git a/source/html/sync.go b/source/html/sync.go index 88237fb..2e64cc7 100644 --- a/source/html/sync.go +++ b/source/html/sync.go @@ -26,63 +26,51 @@ func readHTML(p string) (*html.Node, error) { return html.Parse(htmlFile) } -func SyncHtml(p string) error { - - content, err := os.ReadFile(p) - if err != nil { - return err - } - - currentDir, _ := os.Getwd() - if err := os.Chdir(filepath.Dir(p)); err != nil { - return err - } +type StringNodeMap map[string]*html.Node +type StringListNodeMap map[string][]*html.Node - defer func() { - _ = os.Chdir(currentDir) - }() - - specification := types.SyncSpecification{} - - if err := yaml.Unmarshal(content, &specification); err != nil { - return err - } - - destinationWriteFiles := make(map[string]*html.Node) +func getSourceFileMap(specification types.SyncSpecification) (StringNodeMap, error) { + sourceFiles := make(StringNodeMap) for _, r := range specification.Sync { - sourceFiles := make(map[string]*html.Node) - destinationFiles := make(map[string]*html.Node) - destinationFile := make(map[string][]string) - source := r.Source - destination := r.Destination - exclude := r.Destination.Exclude absSource, err := filepath.Abs(source.Path) if err != nil { - return err + return nil, err } - if err != nil { - return err + // if already read, skip + if _, ok := sourceFiles[absSource]; ok { + continue } if sourceFiles[absSource], err = readHTML(absSource); err != nil { - return err + return nil, err } - for _, d := range destination.Path { + } + + return sourceFiles, nil +} + +func getDestinationFiles(specification types.SyncSpecification) (StringNodeMap, error) { + + fileMap := make(StringNodeMap) + + for _, r := range specification.Sync { + + for _, d := range r.Destination.Path { d, err := filepath.Abs(d) if err != nil { - return err + return nil, err } fileInfo, err := os.Stat(d) if err != nil { - return err + return nil, err } if fileInfo.IsDir() { @@ -99,12 +87,7 @@ func SyncHtml(p string) error { return nil } - excludeFlag, err2 := checkExcludes(exclude, pp) - if err2 != nil { - return err2 - } - - if excludeFlag { + if _, ok := fileMap[pp]; ok { return nil } @@ -113,65 +96,153 @@ func SyncHtml(p string) error { return err } - destinationFiles[pp] = dd - destinationWriteFiles[pp] = dd - destinationFile[absSource] = append(destinationFile[absSource], pp) + fileMap[pp] = dd return nil }); err != nil { - return err + return nil, err } - } else if filepath.Ext(d) == ".html" { - if exclude != nil { - excludeFlag, err2 := checkExcludes(exclude, d) - if err2 != nil { - return err2 - } + } else if filepath.Ext(d) == ".html" { - if excludeFlag { - continue - } + if _, ok := fileMap[d]; ok { + continue } var dd *html.Node if dd, err = readHTML(d); err != nil { - return err + return nil, err } - destinationFiles[d] = dd - destinationWriteFiles[d] = dd - destinationFile[absSource] = append(destinationFile[absSource], d) + fileMap[d] = dd } } - //source := r.Source - //absSource, err := filepath.Abs(source.Path) - //if err != nil { - // return err - //} - sourceSelector := source.Selector + } - query, err := cascadia.Compile(sourceSelector) + return fileMap, nil +} + +func getAllDestinationFilesWithoutExcludes(destination types.Destination) ([]string, error) { + var files []string + + for _, p := range destination.Path { + p, err := filepath.Abs(p) + if err != nil { + return nil, err + } + + if err = filepath.Walk(p, func(pp string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if info.IsDir() { + return nil + } + + ext := filepath.Ext(pp) + if ext != ".html" { + return nil + } + + exclude, err := checkExcludes(destination.Exclude, pp) + if err != nil { + return err + } + + if exclude { + return nil + } + + files = append(files, pp) + + return nil + }); err != nil { + return nil, err + } + + } + + return files, nil +} + +func SyncHtml(p string) error { + + content, err := os.ReadFile(p) + if err != nil { + return err + } + + currentDir, _ := os.Getwd() + if err := os.Chdir(filepath.Dir(p)); err != nil { + return err + } + + defer func() { + _ = os.Chdir(currentDir) + }() + + specification := types.SyncSpecification{} + + if err := yaml.Unmarshal(content, &specification); err != nil { + return err + } + + var sourceFiles StringNodeMap + sourceFiles, err = getSourceFileMap(specification) + if err != nil { + return err + } + + var destinationFiles StringNodeMap + destinationFiles, err = getDestinationFiles(specification) + if err != nil { + return err + } + + changedFiles := make(map[string]struct{}) + for _, r := range specification.Sync { + + source := r.Source + absSource, err := filepath.Abs(source.Path) if err != nil { return err } - s, ok := sourceFiles[absSource] + sourceNode, ok := sourceFiles[absSource] if !ok { return fmt.Errorf("source file isn't found: %s", absSource) } - sourceNode := query.MatchFirst(s) + sourceSelector := source.Selector + query, err := cascadia.Compile(sourceSelector) + if err != nil { + return err + } + + sourceNode = query.MatchFirst(sourceNode) + if sourceNode == nil { + return fmt.Errorf("source selector not found: %s in %s", sourceSelector, absSource) + } + + list, err := getAllDestinationFilesWithoutExcludes(r.Destination) + if err != nil { + return err + } - dp := destinationFile[absSource] - for _, d := range dp { + for _, d := range list { destinationSelector := r.Destination.Selector if destinationSelector == "" { destinationSelector = sourceSelector } - keepMap := make(map[string][]*html.Node) + query, err := cascadia.Compile(destinationSelector) + if err != nil { + return err + } + + keepMap := make(StringListNodeMap) for _, n := range r.Destination.Keep { q, err := cascadia.Compile(n) @@ -190,13 +261,7 @@ func SyncHtml(p string) error { } - query, err := cascadia.Compile(destinationSelector) - if err != nil { - return err - } - destinationData := query.MatchFirst(destinationFiles[d]) - if destinationData == nil { return fmt.Errorf("could not find destination selector %s in %s", destinationSelector, d) } @@ -227,17 +292,24 @@ func SyncHtml(p string) error { n1.Parent.InsertBefore(engine.CloneNode(kk), n1) n1.Parent.RemoveChild(n1) } + } + } + + changedFiles[d] = struct{}{} + } + } - for p, d := range destinationWriteFiles { - fp, err := os.Create(p) + for d, _ := range changedFiles { + + fp, err := os.Create(d) if err != nil { return err } - err = html.Render(fp, d) + err = html.Render(fp, destinationFiles[d]) err2 := fp.Close() if err2 != nil { return err2 @@ -246,6 +318,7 @@ func SyncHtml(p string) error { if err != nil { return err } + } return nil diff --git a/source/types/sync-specification.go b/source/types/sync-specification.go index b6047c1..fc3b1fd 100644 --- a/source/types/sync-specification.go +++ b/source/types/sync-specification.go @@ -21,17 +21,19 @@ func (p *PathOrList) UnmarshalYAML(value *yaml.Node) error { return nil } +type Destination struct { + Selector string `yaml:"selector"` + Path PathOrList `yaml:"path"` + Exclude []string `yaml:"exclude"` + Keep []string `yaml:"keep"` +} + type Sync struct { Source struct { Selector string `yaml:"selector"` Path string `yaml:"path"` } `yaml:"source"` - Destination struct { - Selector string `yaml:"selector"` - Path PathOrList `yaml:"path"` - Exclude []string `yaml:"exclude"` - Keep []string `yaml:"keep"` - } `yaml:"destination"` + Destination Destination `yaml:"destination"` } type SyncSpecification struct { -- GitLab