-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathprocessor.go
More file actions
140 lines (118 loc) · 3.08 KB
/
processor.go
File metadata and controls
140 lines (118 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"bytes"
"encoding/xml"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// Stats tracks processing statistics
type Stats struct {
filesProc int64
bytesProc int64
errors int64
}
// isExcludedPath checks if the path should be excluded
func isExcludedPath(path string, config Config) bool {
if config.unsafeMode {
return false
}
parts := strings.Split(filepath.ToSlash(path), "/")
for _, part := range parts {
for _, excluded := range ExcludedPaths {
if part == excluded {
fmt.Printf("Skipping excluded path: %s (matched %s)\n", path, excluded)
return true
}
}
}
base := filepath.Base(path)
if strings.HasPrefix(base, ".") && base != "." && base != ".." {
fmt.Printf("Skipping hidden file/directory: %s\n", path)
return true
}
return false
}
// processFiles walks through the directory and processes files
func processFiles(config Config, writer io.Writer) (Stats, error) {
var stats Stats
absTargetDir, err := filepath.Abs(config.targetDir)
if err != nil {
return stats, fmt.Errorf("error resolving target directory: %v", err)
}
fmt.Printf("Processing directory: %s\n", absTargetDir)
// Write XML header
io.WriteString(writer, xml.Header)
fmt.Fprintf(writer, "<files>\n")
err = filepath.Walk(absTargetDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
fmt.Printf("Error accessing path %s: %v\n", path, err)
stats.errors++
return nil
}
if info.IsDir() {
if isExcludedPath(path, config) {
fmt.Printf("Skipping excluded directory: %s\n", path)
return filepath.SkipDir
}
return nil
}
if isExcludedPath(path, config) {
return nil
}
if !isFileMatch(path, config) {
return nil
}
// Check file size before processing
if config.maxFileSize > 0 && info.Size() > config.maxFileSize {
fmt.Printf("Skipping file exceeding size limit: %s (%d bytes)\n", path, info.Size())
stats.errors++
return nil
}
relPath, err := filepath.Rel(absTargetDir, path)
if err != nil {
fmt.Printf("Error getting relative path for %s: %v\n", path, err)
stats.errors++
return nil
}
fmt.Printf("Processing: %s\n", relPath)
// Read file content
file, err := os.Open(path)
if err != nil {
fmt.Printf("Error opening file %s: %v\n", path, err)
stats.errors++
return nil
}
defer file.Close()
// Use a buffer with reasonable size
buf := bytes.NewBuffer(make([]byte, 0, 32*1024))
_, err = io.Copy(buf, file)
if err != nil {
fmt.Printf("Error reading file %s: %v\n", path, err)
stats.errors++
return nil
}
// Create file content
content := FileContent{
Name: relPath,
Size: info.Size(),
Content: buf.String(),
}
// Encode to XML
encoder := xml.NewEncoder(writer)
encoder.Indent("", " ")
if err := encoder.Encode(content); err != nil {
fmt.Printf("Error encoding %s: %v\n", relPath, err)
stats.errors++
return nil
}
stats.filesProc++
stats.bytesProc += info.Size()
fmt.Printf("Processed: %s (%.2f KB)\n", relPath, float64(info.Size())/1024)
return nil
})
fmt.Fprintf(writer, "</files>\n")
return stats, err
}