mirror of
https://github.com/vbatts/go-mtree.git
synced 2024-11-21 16:05:40 +00:00
visitor pattern
This commit is contained in:
parent
739d74de3c
commit
cc12bd7a0b
4 changed files with 93 additions and 57 deletions
|
@ -64,67 +64,46 @@ func mutateAction(c *cli.Context) error {
|
||||||
return fmt.Errorf("parsing mtree %s: %w", mtreePath, err)
|
return fmt.Errorf("parsing mtree %s: %w", mtreePath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dropDotDot := 0
|
stripPrefixVisitor := stripPrefixVisitor{
|
||||||
droppedParents := []*mtree.Entry{}
|
prefixes: stripPrexies,
|
||||||
|
}
|
||||||
|
tidyVisitor := tidyVisitor{
|
||||||
|
keepComments: keepComments,
|
||||||
|
keepBlank: keepBlank,
|
||||||
|
}
|
||||||
|
visitors := []Visitor{
|
||||||
|
&stripPrefixVisitor,
|
||||||
|
&tidyVisitor,
|
||||||
|
}
|
||||||
|
|
||||||
|
dropped := []int{}
|
||||||
entries := []mtree.Entry{}
|
entries := []mtree.Entry{}
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
for _, entry := range spec.Entries {
|
for _, entry := range spec.Entries {
|
||||||
|
|
||||||
if !keepComments && entry.Type == mtree.CommentType {
|
if entry.Parent != nil && slices.Contains(dropped, entry.Parent.Pos) {
|
||||||
continue
|
if entry.Type == mtree.DotDotType {
|
||||||
}
|
// directory for this .. has been dropped so shall this
|
||||||
if !keepBlank && entry.Type == mtree.BlankType {
|
continue
|
||||||
continue
|
}
|
||||||
|
entry.Parent = entry.Parent.Parent
|
||||||
|
// TODO: i am not sure if this is the correct behavior
|
||||||
|
entry.Raw = strings.TrimPrefix(entry.Raw, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.Parent != nil && slices.Contains(droppedParents, &entry) {
|
for _, visitor := range visitors {
|
||||||
entry.Parent = nil
|
drop, err := visitor.Visit(&entry)
|
||||||
entry.Type = mtree.FullType
|
|
||||||
entry.Raw = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if entry.Type == mtree.FullType || entry.Type == mtree.RelativeType {
|
|
||||||
fp, err := entry.Path()
|
|
||||||
// fmt.Println("fp", fp, entry.Name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pathSegments := strings.Split(fp, "/")
|
|
||||||
|
|
||||||
for _, prefix := range stripPrexies {
|
if drop {
|
||||||
|
dropped = append(dropped, entry.Pos)
|
||||||
prefixSegments := strings.Split(prefix, "/")
|
continue skip
|
||||||
minLen := int(math.Min(float64(len(pathSegments)), float64(len(prefixSegments))))
|
|
||||||
matches := make([]string, minLen)
|
|
||||||
for i := 0; i < minLen; i++ {
|
|
||||||
if pathSegments[i] == prefixSegments[i] {
|
|
||||||
matches[i] = prefixSegments[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strip := strings.Join(matches, "/")
|
|
||||||
if entry.Type == mtree.FullType {
|
|
||||||
entry.Name = strings.TrimPrefix(entry.Name, strip)
|
|
||||||
entry.Name = strings.TrimPrefix(entry.Name, "/")
|
|
||||||
if entry.Name == "" {
|
|
||||||
continue skip
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if entry.IsDir() {
|
|
||||||
dropDotDot++
|
|
||||||
droppedParents = append(droppedParents, &entry)
|
|
||||||
}
|
|
||||||
if fp == strip {
|
|
||||||
continue skip
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if dropDotDot > 0 && entry.Type == mtree.DotDotType {
|
|
||||||
dropDotDot--
|
|
||||||
continue skip
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entries = append(entries, entry)
|
entries = append(entries, entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,3 +121,61 @@ skip:
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Visitor interface {
|
||||||
|
Visit(entry *mtree.Entry) (bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type tidyVisitor struct {
|
||||||
|
keepComments bool
|
||||||
|
keepBlank bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *tidyVisitor) Visit(entry *mtree.Entry) (bool, error) {
|
||||||
|
if !m.keepComments && entry.Type == mtree.CommentType {
|
||||||
|
return true, nil
|
||||||
|
} else if !m.keepBlank && entry.Type == mtree.BlankType {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type stripPrefixVisitor struct {
|
||||||
|
prefixes []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *stripPrefixVisitor) Visit(entry *mtree.Entry) (bool, error) {
|
||||||
|
if entry.Type != mtree.FullType && entry.Type != mtree.RelativeType {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fp, err := entry.Path()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
pathSegments := strings.Split(fp, "/")
|
||||||
|
|
||||||
|
for _, prefix := range m.prefixes {
|
||||||
|
|
||||||
|
prefixSegments := strings.Split(prefix, "/")
|
||||||
|
minLen := int(math.Min(float64(len(pathSegments)), float64(len(prefixSegments))))
|
||||||
|
matches := make([]string, minLen)
|
||||||
|
for i := 0; i < minLen; i++ {
|
||||||
|
if pathSegments[i] == prefixSegments[i] {
|
||||||
|
matches[i] = prefixSegments[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strip := strings.Join(matches, "/")
|
||||||
|
if entry.Type == mtree.FullType {
|
||||||
|
entry.Name = strings.TrimPrefix(entry.Name, strip)
|
||||||
|
entry.Name = strings.TrimPrefix(entry.Name, "/")
|
||||||
|
if entry.Name == "" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
} else if fp == strip {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
5
entry.go
5
entry.go
|
@ -134,7 +134,10 @@ func (e Entry) String() string {
|
||||||
if e.Type == SpecialType || e.Type == FullType || inKeyValSlice("type=dir", e.Keywords) {
|
if e.Type == SpecialType || e.Type == FullType || inKeyValSlice("type=dir", e.Keywords) {
|
||||||
return fmt.Sprintf("%s %s", e.Name, strings.Join(KeyValToString(e.Keywords), " "))
|
return fmt.Sprintf("%s %s", e.Name, strings.Join(KeyValToString(e.Keywords), " "))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf(" %s %s", e.Name, strings.Join(KeyValToString(e.Keywords), " "))
|
if e.Parent != nil && e.Type != DotDotType {
|
||||||
|
return fmt.Sprintf(" %s %s", e.Name, strings.Join(KeyValToString(e.Keywords), " "))
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s %s", e.Name, strings.Join(KeyValToString(e.Keywords), " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllKeys returns the full set of KeyVal for the given entry, based on the
|
// AllKeys returns the full set of KeyVal for the given entry, based on the
|
||||||
|
|
1
parse.go
1
parse.go
|
@ -58,6 +58,7 @@ func ParseSpec(r io.Reader) (*DirectoryHierarchy, error) {
|
||||||
e.Type = DotDotType
|
e.Type = DotDotType
|
||||||
e.Raw = str
|
e.Raw = str
|
||||||
if creator.curDir != nil {
|
if creator.curDir != nil {
|
||||||
|
e.Parent = creator.curDir
|
||||||
creator.curDir = creator.curDir.Parent
|
creator.curDir = creator.curDir.Parent
|
||||||
}
|
}
|
||||||
// nothing else to do here
|
// nothing else to do here
|
||||||
|
|
|
@ -2,18 +2,13 @@
|
||||||
lib type=dir mode=0644
|
lib type=dir mode=0644
|
||||||
foo mode=0644 size=12288 time=1457644483.833957552 type=file
|
foo mode=0644 size=12288 time=1457644483.833957552 type=file
|
||||||
|
|
||||||
# ./lib/dir
|
|
||||||
lib type=dir mode=0644
|
|
||||||
|
|
||||||
dir type=dir mode=0644
|
|
||||||
|
|
||||||
# ./lib
|
|
||||||
..
|
..
|
||||||
|
|
||||||
# .
|
./lib type=dir mode=0644
|
||||||
..
|
|
||||||
|
|
||||||
|
ayo mode=0644 size=12288 time=1457644483.833957552 type=file
|
||||||
|
|
||||||
# ./lib/dir/sub
|
|
||||||
lib/dir/sub type=dir
|
lib/dir/sub type=dir
|
||||||
lib/dir/sub/file.txt type=file
|
lib/dir/sub/file.txt type=file
|
||||||
|
|
Loading…
Reference in a new issue