From d4615a2ad8f2c56e1b0dd1dcc064242c1f183b16 Mon Sep 17 00:00:00 2001 From: Virgil Date: Mon, 30 Mar 2026 21:48:42 +0000 Subject: [PATCH] refactor(ax): align backend names and examples --- datanode/client.go | 76 ++++++++++----------- node/node.go | 163 +++++++++++++++++++-------------------------- s3/s3.go | 76 ++++++++++----------- sqlite/sqlite.go | 70 +++++++++---------- 4 files changed, 176 insertions(+), 209 deletions(-) diff --git a/datanode/client.go b/datanode/client.go index 008b662..f72f0ac 100644 --- a/datanode/client.go +++ b/datanode/client.go @@ -20,14 +20,14 @@ import ( ) var ( - dataNodeWalkDir = func(fsys fs.FS, root string, fn fs.WalkDirFunc) error { - return fs.WalkDir(fsys, root, fn) + dataNodeWalkDir = func(fileSystem fs.FS, root string, callback fs.WalkDirFunc) error { + return fs.WalkDir(fileSystem, root, callback) } - dataNodeOpen = func(dn *borgdatanode.DataNode, name string) (fs.File, error) { - return dn.Open(name) + dataNodeOpen = func(dataNode *borgdatanode.DataNode, filePath string) (fs.File, error) { + return dataNode.Open(filePath) } - dataNodeReadAll = func(r goio.Reader) ([]byte, error) { - return goio.ReadAll(r) + dataNodeReadAll = func(reader goio.Reader) ([]byte, error) { + return goio.ReadAll(reader) } ) @@ -109,13 +109,13 @@ func (medium *Medium) Read(filePath string) (string, error) { defer medium.mu.RUnlock() filePath = normaliseEntryPath(filePath) - f, err := medium.dataNode.Open(filePath) + file, err := medium.dataNode.Open(filePath) if err != nil { return "", core.E("datanode.Read", core.Concat("not found: ", filePath), fs.ErrNotExist) } - defer f.Close() + defer file.Close() - info, err := f.Stat() + info, err := file.Stat() if err != nil { return "", core.E("datanode.Read", core.Concat("stat failed: ", filePath), err) } @@ -123,7 +123,7 @@ func (medium *Medium) Read(filePath string) (string, error) { return "", core.E("datanode.Read", core.Concat("is a directory: ", filePath), fs.ErrInvalid) } - data, err := goio.ReadAll(f) + data, err := goio.ReadAll(file) if err != nil { return "", core.E("datanode.Read", core.Concat("read failed: ", filePath), err) } @@ -461,11 +461,11 @@ func (medium *Medium) ReadStream(filePath string) (goio.ReadCloser, error) { defer medium.mu.RUnlock() filePath = normaliseEntryPath(filePath) - f, err := medium.dataNode.Open(filePath) + file, err := medium.dataNode.Open(filePath) if err != nil { return nil, core.E("datanode.ReadStream", core.Concat("not found: ", filePath), fs.ErrNotExist) } - return f.(goio.ReadCloser), nil + return file.(goio.ReadCloser), nil } func (medium *Medium) WriteStream(filePath string) (goio.WriteCloser, error) { @@ -538,13 +538,13 @@ func (medium *Medium) collectAllLocked() ([]string, error) { return names, err } -func (medium *Medium) readFileLocked(name string) ([]byte, error) { - f, err := dataNodeOpen(medium.dataNode, name) +func (medium *Medium) readFileLocked(filePath string) ([]byte, error) { + file, err := dataNodeOpen(medium.dataNode, filePath) if err != nil { return nil, err } - data, readErr := dataNodeReadAll(f) - closeErr := f.Close() + data, readErr := dataNodeReadAll(file) + closeErr := file.Close() if readErr != nil { return nil, readErr } @@ -562,7 +562,7 @@ func (medium *Medium) removeFileLocked(target string) error { if err != nil { return err } - newDN := borgdatanode.New() + newDataNode := borgdatanode.New() for _, name := range entries { if name == target { continue @@ -571,9 +571,9 @@ func (medium *Medium) removeFileLocked(target string) error { if err != nil { return err } - newDN.AddData(name, data) + newDataNode.AddData(name, data) } - medium.dataNode = newDN + medium.dataNode = newDataNode return nil } @@ -585,17 +585,17 @@ type writeCloser struct { buf []byte } -func (w *writeCloser) Write(p []byte) (int, error) { - w.buf = append(w.buf, p...) - return len(p), nil +func (writer *writeCloser) Write(data []byte) (int, error) { + writer.buf = append(writer.buf, data...) + return len(data), nil } -func (w *writeCloser) Close() error { - w.medium.mu.Lock() - defer w.medium.mu.Unlock() +func (writer *writeCloser) Close() error { + writer.medium.mu.Lock() + defer writer.medium.mu.Unlock() - w.medium.dataNode.AddData(w.path, w.buf) - w.medium.ensureDirsLocked(path.Dir(w.path)) + writer.medium.dataNode.AddData(writer.path, writer.buf) + writer.medium.ensureDirsLocked(path.Dir(writer.path)) return nil } @@ -605,14 +605,14 @@ type dirEntry struct { name string } -func (d *dirEntry) Name() string { return d.name } +func (entry *dirEntry) Name() string { return entry.name } -func (d *dirEntry) IsDir() bool { return true } +func (entry *dirEntry) IsDir() bool { return true } -func (d *dirEntry) Type() fs.FileMode { return fs.ModeDir } +func (entry *dirEntry) Type() fs.FileMode { return fs.ModeDir } -func (d *dirEntry) Info() (fs.FileInfo, error) { - return &fileInfo{name: d.name, isDir: true, mode: fs.ModeDir | 0755}, nil +func (entry *dirEntry) Info() (fs.FileInfo, error) { + return &fileInfo{name: entry.name, isDir: true, mode: fs.ModeDir | 0755}, nil } type fileInfo struct { @@ -623,14 +623,14 @@ type fileInfo struct { isDir bool } -func (fi *fileInfo) Name() string { return fi.name } +func (info *fileInfo) Name() string { return info.name } -func (fi *fileInfo) Size() int64 { return fi.size } +func (info *fileInfo) Size() int64 { return info.size } -func (fi *fileInfo) Mode() fs.FileMode { return fi.mode } +func (info *fileInfo) Mode() fs.FileMode { return info.mode } -func (fi *fileInfo) ModTime() time.Time { return fi.modTime } +func (info *fileInfo) ModTime() time.Time { return info.modTime } -func (fi *fileInfo) IsDir() bool { return fi.isDir } +func (info *fileInfo) IsDir() bool { return info.isDir } -func (fi *fileInfo) Sys() any { return nil } +func (info *fileInfo) Sys() any { return nil } diff --git a/node/node.go b/node/node.go index 82d7dfe..2dab424 100644 --- a/node/node.go +++ b/node/node.go @@ -1,9 +1,9 @@ // Package node keeps io.Medium data in memory. // -// nodeTree := node.New() -// nodeTree.AddData("config/app.yaml", []byte("port: 8080")) -// snapshot, _ := nodeTree.ToTar() -// restored, _ := node.FromTar(snapshot) +// Example: nodeTree := node.New() +// Example: nodeTree.AddData("config/app.yaml", []byte("port: 8080")) +// Example: snapshot, _ := nodeTree.ToTar() +// Example: restored, _ := node.FromTar(snapshot) package node import ( @@ -21,14 +21,13 @@ import ( ) // Example: nodeTree := node.New() -// nodeTree.AddData("config/app.yaml", []byte("port: 8080")) -// snapshot, _ := nodeTree.ToTar() -// restored, _ := node.FromTar(snapshot) +// Example: nodeTree.AddData("config/app.yaml", []byte("port: 8080")) +// Example: snapshot, _ := nodeTree.ToTar() +// Example: restored, _ := node.FromTar(snapshot) type Node struct { files map[string]*dataFile } -// Compile-time interface checks. var _ coreio.Medium = (*Node)(nil) var _ fs.ReadFileFS = (*Node)(nil) @@ -36,9 +35,7 @@ func New() *Node { return &Node{files: make(map[string]*dataFile)} } -// ---------- Node-specific methods ---------- - -// AddData stages content in the in-memory filesystem. +// Example: nodeTree.AddData("config/app.yaml", []byte("port: 8080")) func (node *Node) AddData(name string, content []byte) { name = core.TrimPrefix(name, "/") if name == "" { @@ -55,7 +52,7 @@ func (node *Node) AddData(name string, content []byte) { } } -// ToTar serialises the entire in-memory tree to a tar archive. +// Example: snapshot, _ := nodeTree.ToTar() func (node *Node) ToTar() ([]byte, error) { buf := new(bytes.Buffer) tw := tar.NewWriter(buf) @@ -91,7 +88,7 @@ func FromTar(data []byte) (*Node, error) { return n, nil } -// LoadTar replaces the in-memory tree with the contents of a tar archive. +// Example: _ = nodeTree.LoadTar(snapshot) func (node *Node) LoadTar(data []byte) error { newFiles := make(map[string]*dataFile) tr := tar.NewReader(bytes.NewReader(data)) @@ -142,11 +139,7 @@ type WalkOptions struct { SkipErrors bool } -// WalkWithOptions walks the in-memory tree with an explicit configuration. -// -// nodeTree := New() -// options := WalkOptions{MaxDepth: 1, SkipErrors: true} -// _ = nodeTree.WalkWithOptions(".", func(path string, entry fs.DirEntry, err error) error { return nil }, options) +// Example: _ = nodeTree.WalkWithOptions(".", callback, node.WalkOptions{MaxDepth: 1, SkipErrors: true}) func (node *Node) WalkWithOptions(root string, fn fs.WalkDirFunc, options WalkOptions) error { if options.SkipErrors { // If root doesn't exist, silently return nil. @@ -184,20 +177,20 @@ func (node *Node) WalkWithOptions(root string, fn fs.WalkDirFunc, options WalkOp func (node *Node) ReadFile(name string) ([]byte, error) { name = core.TrimPrefix(name, "/") - f, ok := node.files[name] + file, ok := node.files[name] if !ok { return nil, core.E("node.ReadFile", core.Concat("path not found: ", name), fs.ErrNotExist) } // Return a copy to prevent callers from mutating internal state. - result := make([]byte, len(f.content)) - copy(result, f.content) + result := make([]byte, len(file.content)) + copy(result, file.content) return result, nil } -// CopyFile copies a file from the in-memory tree to the local filesystem. +// Example: _ = nodeTree.CopyFile("config/app.yaml", "/tmp/app.yaml", 0644) func (node *Node) CopyFile(sourcePath, destinationPath string, perm fs.FileMode) error { sourcePath = core.TrimPrefix(sourcePath, "/") - f, ok := node.files[sourcePath] + file, ok := node.files[sourcePath] if !ok { // Check if it's a directory — can't copy directories this way. info, err := node.Stat(sourcePath) @@ -213,15 +206,10 @@ func (node *Node) CopyFile(sourcePath, destinationPath string, perm fs.FileMode) if parent != "." && parent != "" && parent != destinationPath && !coreio.Local.IsDir(parent) { return &fs.PathError{Op: "copyfile", Path: destinationPath, Err: fs.ErrNotExist} } - return coreio.Local.WriteMode(destinationPath, string(f.content), perm) + return coreio.Local.WriteMode(destinationPath, string(file.content), perm) } -// CopyTo copies a file (or directory tree) from the node to any Medium. -// -// Example usage: -// -// dst := io.NewMockMedium() -// _ = node.CopyTo(dst, "config", "backup/config") +// Example: _ = nodeTree.CopyTo(io.NewMockMedium(), "config", "backup/config") func (node *Node) CopyTo(target coreio.Medium, sourcePath, destPath string) error { sourcePath = core.TrimPrefix(sourcePath, "/") info, err := node.Stat(sourcePath) @@ -231,11 +219,11 @@ func (node *Node) CopyTo(target coreio.Medium, sourcePath, destPath string) erro if !info.IsDir() { // Single file copy - f, ok := node.files[sourcePath] + file, ok := node.files[sourcePath] if !ok { return core.E("node.CopyTo", core.Concat("path not found: ", sourcePath), fs.ErrNotExist) } - return target.Write(destPath, string(f.content)) + return target.Write(destPath, string(file.content)) } // Directory: walk and copy all files underneath @@ -244,7 +232,7 @@ func (node *Node) CopyTo(target coreio.Medium, sourcePath, destPath string) erro prefix += "/" } - for filePath, f := range node.files { + for filePath, file := range node.files { if !core.HasPrefix(filePath, prefix) && filePath != sourcePath { continue } @@ -253,7 +241,7 @@ func (node *Node) CopyTo(target coreio.Medium, sourcePath, destPath string) erro if rel != "" { dest = core.Concat(destPath, "/", rel) } - if err := target.Write(dest, string(f.content)); err != nil { + if err := target.Write(dest, string(file.content)); err != nil { return err } } @@ -264,8 +252,8 @@ func (node *Node) CopyTo(target coreio.Medium, sourcePath, destPath string) erro func (node *Node) Open(name string) (fs.File, error) { name = core.TrimPrefix(name, "/") - if file, ok := node.files[name]; ok { - return &dataFileReader{file: file}, nil + if dataFile, ok := node.files[name]; ok { + return &dataFileReader{file: dataFile}, nil } // Check if it's a directory prefix := name + "/" @@ -282,8 +270,8 @@ func (node *Node) Open(name string) (fs.File, error) { func (node *Node) Stat(name string) (fs.FileInfo, error) { name = core.TrimPrefix(name, "/") - if file, ok := node.files[name]; ok { - return file.Stat() + if dataFile, ok := node.files[name]; ok { + return dataFile.Stat() } // Check if it's a directory prefix := name + "/" @@ -351,11 +339,11 @@ func (node *Node) ReadDir(name string) ([]fs.DirEntry, error) { func (node *Node) Read(filePath string) (string, error) { filePath = core.TrimPrefix(filePath, "/") - f, ok := node.files[filePath] + file, ok := node.files[filePath] if !ok { return "", core.E("node.Read", core.Concat("path not found: ", filePath), fs.ErrNotExist) } - return string(f.content), nil + return string(file.content), nil } func (node *Node) Write(filePath, content string) error { @@ -439,13 +427,13 @@ func (node *Node) Rename(oldPath, newPath string) error { oldPath = core.TrimPrefix(oldPath, "/") newPath = core.TrimPrefix(newPath, "/") - f, ok := node.files[oldPath] + file, ok := node.files[oldPath] if !ok { return core.E("node.Rename", core.Concat("path not found: ", oldPath), fs.ErrNotExist) } - f.name = newPath - node.files[newPath] = f + file.name = newPath + node.files[newPath] = file delete(node.files, oldPath) return nil } @@ -468,19 +456,19 @@ func (node *Node) Create(filePath string) (goio.WriteCloser, error) { func (node *Node) Append(filePath string) (goio.WriteCloser, error) { filePath = core.TrimPrefix(filePath, "/") var existing []byte - if f, ok := node.files[filePath]; ok { - existing = make([]byte, len(f.content)) - copy(existing, f.content) + if file, ok := node.files[filePath]; ok { + existing = make([]byte, len(file.content)) + copy(existing, file.content) } return &nodeWriter{node: node, path: filePath, buf: existing}, nil } func (node *Node) ReadStream(filePath string) (goio.ReadCloser, error) { - f, err := node.Open(filePath) + file, err := node.Open(filePath) if err != nil { return nil, err } - return goio.NopCloser(f), nil + return goio.NopCloser(file), nil } func (node *Node) WriteStream(filePath string) (goio.WriteCloser, error) { @@ -496,15 +484,15 @@ type nodeWriter struct { buf []byte } -func (w *nodeWriter) Write(p []byte) (int, error) { - w.buf = append(w.buf, p...) - return len(p), nil +func (writer *nodeWriter) Write(data []byte) (int, error) { + writer.buf = append(writer.buf, data...) + return len(data), nil } -func (w *nodeWriter) Close() error { - w.node.files[w.path] = &dataFile{ - name: w.path, - content: w.buf, +func (writer *nodeWriter) Close() error { + writer.node.files[writer.path] = &dataFile{ + name: writer.path, + content: writer.buf, modTime: time.Now(), } return nil @@ -517,26 +505,26 @@ type dataFile struct { modTime time.Time } -func (d *dataFile) Stat() (fs.FileInfo, error) { return &dataFileInfo{file: d}, nil } +func (file *dataFile) Stat() (fs.FileInfo, error) { return &dataFileInfo{file: file}, nil } -func (d *dataFile) Read(_ []byte) (int, error) { return 0, goio.EOF } +func (file *dataFile) Read(_ []byte) (int, error) { return 0, goio.EOF } -func (d *dataFile) Close() error { return nil } +func (file *dataFile) Close() error { return nil } // dataFileInfo implements fs.FileInfo for a dataFile. type dataFileInfo struct{ file *dataFile } -func (d *dataFileInfo) Name() string { return path.Base(d.file.name) } +func (info *dataFileInfo) Name() string { return path.Base(info.file.name) } -func (d *dataFileInfo) Size() int64 { return int64(len(d.file.content)) } +func (info *dataFileInfo) Size() int64 { return int64(len(info.file.content)) } -func (d *dataFileInfo) Mode() fs.FileMode { return 0444 } +func (info *dataFileInfo) Mode() fs.FileMode { return 0444 } -func (d *dataFileInfo) ModTime() time.Time { return d.file.modTime } +func (info *dataFileInfo) ModTime() time.Time { return info.file.modTime } -func (d *dataFileInfo) IsDir() bool { return false } +func (info *dataFileInfo) IsDir() bool { return false } -func (d *dataFileInfo) Sys() any { return nil } +func (info *dataFileInfo) Sys() any { return nil } // dataFileReader implements fs.File for reading a dataFile. type dataFileReader struct { @@ -544,16 +532,16 @@ type dataFileReader struct { reader *bytes.Reader } -func (d *dataFileReader) Stat() (fs.FileInfo, error) { return d.file.Stat() } +func (reader *dataFileReader) Stat() (fs.FileInfo, error) { return reader.file.Stat() } -func (d *dataFileReader) Read(p []byte) (int, error) { - if d.reader == nil { - d.reader = bytes.NewReader(d.file.content) +func (reader *dataFileReader) Read(buffer []byte) (int, error) { + if reader.reader == nil { + reader.reader = bytes.NewReader(reader.file.content) } - return d.reader.Read(p) + return reader.reader.Read(buffer) } -func (d *dataFileReader) Close() error { return nil } +func (reader *dataFileReader) Close() error { return nil } // dirInfo implements fs.FileInfo for an implicit directory. type dirInfo struct { @@ -561,17 +549,17 @@ type dirInfo struct { modTime time.Time } -func (d *dirInfo) Name() string { return d.name } +func (info *dirInfo) Name() string { return info.name } -func (d *dirInfo) Size() int64 { return 0 } +func (info *dirInfo) Size() int64 { return 0 } -func (d *dirInfo) Mode() fs.FileMode { return fs.ModeDir | 0555 } +func (info *dirInfo) Mode() fs.FileMode { return fs.ModeDir | 0555 } -func (d *dirInfo) ModTime() time.Time { return d.modTime } +func (info *dirInfo) ModTime() time.Time { return info.modTime } -func (d *dirInfo) IsDir() bool { return true } +func (info *dirInfo) IsDir() bool { return true } -func (d *dirInfo) Sys() any { return nil } +func (info *dirInfo) Sys() any { return nil } // dirFile implements fs.File for a directory. type dirFile struct { @@ -579,38 +567,25 @@ type dirFile struct { modTime time.Time } -func (d *dirFile) Stat() (fs.FileInfo, error) { - return &dirInfo{name: path.Base(d.path), modTime: d.modTime}, nil +func (directory *dirFile) Stat() (fs.FileInfo, error) { + return &dirInfo{name: path.Base(directory.path), modTime: directory.modTime}, nil } -func (d *dirFile) Read([]byte) (int, error) { - return 0, core.E("node.dirFile.Read", core.Concat("cannot read directory: ", d.path), &fs.PathError{Op: "read", Path: d.path, Err: fs.ErrInvalid}) +func (directory *dirFile) Read([]byte) (int, error) { + return 0, core.E("node.dirFile.Read", core.Concat("cannot read directory: ", directory.path), &fs.PathError{Op: "read", Path: directory.path, Err: fs.ErrInvalid}) } -func (d *dirFile) Close() error { return nil } +func (directory *dirFile) Close() error { return nil } -// Ensure Node implements fs.FS so WalkDir works. var _ fs.FS = (*Node)(nil) -// Ensure Node also satisfies fs.StatFS and fs.ReadDirFS for WalkDir. var _ fs.StatFS = (*Node)(nil) var _ fs.ReadDirFS = (*Node)(nil) -// Unexported helper: ensure ReadStream result also satisfies fs.File -// (for cases where callers do a type assertion). var _ goio.ReadCloser = goio.NopCloser(nil) -// Ensure nodeWriter satisfies goio.WriteCloser. var _ goio.WriteCloser = (*nodeWriter)(nil) -// Ensure dirFile satisfies fs.File. var _ fs.File = (*dirFile)(nil) -// Ensure dataFileReader satisfies fs.File. var _ fs.File = (*dataFileReader)(nil) - -// ReadDirFile is not needed since fs.WalkDir works via ReadDirFS on the FS itself, -// but we need the Node to satisfy fs.ReadDirFS. - -// ensure all internal compile-time checks are grouped above -// no further type assertions needed diff --git a/s3/s3.go b/s3/s3.go index c1b270b..04096b4 100644 --- a/s3/s3.go +++ b/s3/s3.go @@ -1,8 +1,8 @@ // Package s3 stores io.Medium data in S3 objects. // -// client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"}) -// medium, _ := s3.New(s3.Options{Bucket: "backups", Client: client, Prefix: "daily/"}) -// _ = medium.Write("reports/daily.txt", "done") +// Example: client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"}) +// Example: medium, _ := s3.New(s3.Options{Bucket: "backups", Client: client, Prefix: "daily/"}) +// Example: _ = medium.Write("reports/daily.txt", "done") package s3 import ( @@ -22,7 +22,7 @@ import ( ) // Example: client := awss3.NewFromConfig(aws.Config{Region: "us-east-1"}) -// medium, _ := s3.New(s3.Options{Bucket: "backups", Client: client, Prefix: "daily/"}) +// Example: medium, _ := s3.New(s3.Options{Bucket: "backups", Client: client, Prefix: "daily/"}) type Client interface { GetObject(ctx context.Context, params *awss3.GetObjectInput, optFns ...func(*awss3.Options)) (*awss3.GetObjectOutput, error) PutObject(ctx context.Context, params *awss3.PutObjectInput, optFns ...func(*awss3.Options)) (*awss3.PutObjectOutput, error) @@ -34,7 +34,7 @@ type Client interface { } // Example: medium, _ := s3.New(s3.Options{Bucket: "backups", Client: client, Prefix: "daily/"}) -// _ = medium.Write("reports/daily.txt", "done") +// Example: _ = medium.Write("reports/daily.txt", "done") type Medium struct { client Client bucket string @@ -92,7 +92,7 @@ func normalisePrefix(prefix string) string { } // Example: medium, _ := s3.New(s3.Options{Bucket: "backups", Client: client, Prefix: "daily/"}) -// _ = medium.Write("reports/daily.txt", "done") +// Example: _ = medium.Write("reports/daily.txt", "done") func New(options Options) (*Medium, error) { if options.Bucket == "" { return nil, core.E("s3.New", "bucket name is required", nil) @@ -331,11 +331,11 @@ func (medium *Medium) List(filePath string) ([]fs.DirEntry, error) { } // Common prefixes are "directories" - for _, cp := range listOut.CommonPrefixes { - if cp.Prefix == nil { + for _, commonPrefix := range listOut.CommonPrefixes { + if commonPrefix.Prefix == nil { continue } - name := core.TrimPrefix(*cp.Prefix, prefix) + name := core.TrimPrefix(*commonPrefix.Prefix, prefix) name = core.TrimSuffix(name, "/") if name == "" { continue @@ -568,7 +568,6 @@ func (medium *Medium) IsDir(filePath string) bool { // --- Internal types --- -// fileInfo implements fs.FileInfo for S3 objects. type fileInfo struct { name string size int64 @@ -577,19 +576,18 @@ type fileInfo struct { isDir bool } -func (fi *fileInfo) Name() string { return fi.name } +func (info *fileInfo) Name() string { return info.name } -func (fi *fileInfo) Size() int64 { return fi.size } +func (info *fileInfo) Size() int64 { return info.size } -func (fi *fileInfo) Mode() fs.FileMode { return fi.mode } +func (info *fileInfo) Mode() fs.FileMode { return info.mode } -func (fi *fileInfo) ModTime() time.Time { return fi.modTime } +func (info *fileInfo) ModTime() time.Time { return info.modTime } -func (fi *fileInfo) IsDir() bool { return fi.isDir } +func (info *fileInfo) IsDir() bool { return info.isDir } -func (fi *fileInfo) Sys() any { return nil } +func (info *fileInfo) Sys() any { return nil } -// dirEntry implements fs.DirEntry for S3 listings. type dirEntry struct { name string isDir bool @@ -597,15 +595,14 @@ type dirEntry struct { info fs.FileInfo } -func (de *dirEntry) Name() string { return de.name } +func (entry *dirEntry) Name() string { return entry.name } -func (de *dirEntry) IsDir() bool { return de.isDir } +func (entry *dirEntry) IsDir() bool { return entry.isDir } -func (de *dirEntry) Type() fs.FileMode { return de.mode.Type() } +func (entry *dirEntry) Type() fs.FileMode { return entry.mode.Type() } -func (de *dirEntry) Info() (fs.FileInfo, error) { return de.info, nil } +func (entry *dirEntry) Info() (fs.FileInfo, error) { return entry.info, nil } -// s3File implements fs.File for S3 objects. type s3File struct { name string content []byte @@ -614,45 +611,44 @@ type s3File struct { modTime time.Time } -func (f *s3File) Stat() (fs.FileInfo, error) { +func (file *s3File) Stat() (fs.FileInfo, error) { return &fileInfo{ - name: f.name, - size: int64(len(f.content)), + name: file.name, + size: int64(len(file.content)), mode: 0644, - modTime: f.modTime, + modTime: file.modTime, }, nil } -func (f *s3File) Read(b []byte) (int, error) { - if f.offset >= int64(len(f.content)) { +func (file *s3File) Read(buffer []byte) (int, error) { + if file.offset >= int64(len(file.content)) { return 0, goio.EOF } - n := copy(b, f.content[f.offset:]) - f.offset += int64(n) + n := copy(buffer, file.content[file.offset:]) + file.offset += int64(n) return n, nil } -func (f *s3File) Close() error { +func (file *s3File) Close() error { return nil } -// s3WriteCloser buffers writes and uploads to S3 on Close. type s3WriteCloser struct { medium *Medium key string data []byte } -func (w *s3WriteCloser) Write(p []byte) (int, error) { - w.data = append(w.data, p...) - return len(p), nil +func (writer *s3WriteCloser) Write(data []byte) (int, error) { + writer.data = append(writer.data, data...) + return len(data), nil } -func (w *s3WriteCloser) Close() error { - _, err := w.medium.client.PutObject(context.Background(), &awss3.PutObjectInput{ - Bucket: aws.String(w.medium.bucket), - Key: aws.String(w.key), - Body: bytes.NewReader(w.data), +func (writer *s3WriteCloser) Close() error { + _, err := writer.medium.client.PutObject(context.Background(), &awss3.PutObjectInput{ + Bucket: aws.String(writer.medium.bucket), + Key: aws.String(writer.key), + Body: bytes.NewReader(writer.data), }) if err != nil { return core.E("s3.writeCloser.Close", "failed to upload on close", err) diff --git a/sqlite/sqlite.go b/sqlite/sqlite.go index bd02cca..bbd1aa3 100644 --- a/sqlite/sqlite.go +++ b/sqlite/sqlite.go @@ -1,7 +1,7 @@ // Package sqlite stores io.Medium content in SQLite. // -// medium, _ := sqlite.New(sqlite.Options{Path: ":memory:"}) -// _ = medium.Write("config/app.yaml", "port: 8080") +// Example: medium, _ := sqlite.New(sqlite.Options{Path: ":memory:"}) +// Example: _ = medium.Write("config/app.yaml", "port: 8080") package sqlite import ( @@ -19,7 +19,7 @@ import ( ) // Example: medium, _ := sqlite.New(sqlite.Options{Path: ":memory:"}) -// _ = medium.Write("config/app.yaml", "port: 8080") +// Example: _ = medium.Write("config/app.yaml", "port: 8080") type Medium struct { database *sql.DB table string @@ -42,7 +42,7 @@ func normaliseTableName(table string) string { } // Example: medium, _ := sqlite.New(sqlite.Options{Path: ":memory:", Table: "files"}) -// _ = medium.Write("config/app.yaml", "port: 8080") +// Example: _ = medium.Write("config/app.yaml", "port: 8080") func New(options Options) (*Medium, error) { if options.Path == "" { return nil, core.E("sqlite.New", "database path is required", nil) @@ -78,7 +78,7 @@ func New(options Options) (*Medium, error) { return medium, nil } -// Close closes the underlying database connection. +// Example: _ = medium.Close() func (medium *Medium) Close() error { if medium.database != nil { return medium.database.Close() @@ -583,7 +583,6 @@ func (medium *Medium) IsDir(filePath string) bool { // --- Internal types --- -// fileInfo implements fs.FileInfo for SQLite entries. type fileInfo struct { name string size int64 @@ -592,19 +591,18 @@ type fileInfo struct { isDir bool } -func (fi *fileInfo) Name() string { return fi.name } +func (info *fileInfo) Name() string { return info.name } -func (fi *fileInfo) Size() int64 { return fi.size } +func (info *fileInfo) Size() int64 { return info.size } -func (fi *fileInfo) Mode() fs.FileMode { return fi.mode } +func (info *fileInfo) Mode() fs.FileMode { return info.mode } -func (fi *fileInfo) ModTime() time.Time { return fi.modTime } +func (info *fileInfo) ModTime() time.Time { return info.modTime } -func (fi *fileInfo) IsDir() bool { return fi.isDir } +func (info *fileInfo) IsDir() bool { return info.isDir } -func (fi *fileInfo) Sys() any { return nil } +func (info *fileInfo) Sys() any { return nil } -// dirEntry implements fs.DirEntry for SQLite listings. type dirEntry struct { name string isDir bool @@ -612,15 +610,14 @@ type dirEntry struct { info fs.FileInfo } -func (de *dirEntry) Name() string { return de.name } +func (entry *dirEntry) Name() string { return entry.name } -func (de *dirEntry) IsDir() bool { return de.isDir } +func (entry *dirEntry) IsDir() bool { return entry.isDir } -func (de *dirEntry) Type() fs.FileMode { return de.mode.Type() } +func (entry *dirEntry) Type() fs.FileMode { return entry.mode.Type() } -func (de *dirEntry) Info() (fs.FileInfo, error) { return de.info, nil } +func (entry *dirEntry) Info() (fs.FileInfo, error) { return entry.info, nil } -// sqliteFile implements fs.File for SQLite entries. type sqliteFile struct { name string content []byte @@ -629,48 +626,47 @@ type sqliteFile struct { modTime time.Time } -func (f *sqliteFile) Stat() (fs.FileInfo, error) { +func (file *sqliteFile) Stat() (fs.FileInfo, error) { return &fileInfo{ - name: f.name, - size: int64(len(f.content)), - mode: f.mode, - modTime: f.modTime, + name: file.name, + size: int64(len(file.content)), + mode: file.mode, + modTime: file.modTime, }, nil } -func (f *sqliteFile) Read(b []byte) (int, error) { - if f.offset >= int64(len(f.content)) { +func (file *sqliteFile) Read(buffer []byte) (int, error) { + if file.offset >= int64(len(file.content)) { return 0, goio.EOF } - n := copy(b, f.content[f.offset:]) - f.offset += int64(n) + n := copy(buffer, file.content[file.offset:]) + file.offset += int64(n) return n, nil } -func (f *sqliteFile) Close() error { +func (file *sqliteFile) Close() error { return nil } -// sqliteWriteCloser buffers writes and stores to SQLite on Close. type sqliteWriteCloser struct { medium *Medium path string data []byte } -func (w *sqliteWriteCloser) Write(p []byte) (int, error) { - w.data = append(w.data, p...) - return len(p), nil +func (writer *sqliteWriteCloser) Write(data []byte) (int, error) { + writer.data = append(writer.data, data...) + return len(data), nil } -func (w *sqliteWriteCloser) Close() error { - _, err := w.medium.database.Exec( - `INSERT INTO `+w.medium.table+` (path, content, mode, is_dir, mtime) VALUES (?, ?, 420, FALSE, ?) +func (writer *sqliteWriteCloser) Close() error { + _, err := writer.medium.database.Exec( + `INSERT INTO `+writer.medium.table+` (path, content, mode, is_dir, mtime) VALUES (?, ?, 420, FALSE, ?) ON CONFLICT(path) DO UPDATE SET content = excluded.content, is_dir = FALSE, mtime = excluded.mtime`, - w.path, w.data, time.Now().UTC(), + writer.path, writer.data, time.Now().UTC(), ) if err != nil { - return core.E("sqlite.WriteCloser.Close", core.Concat("store failed: ", w.path), err) + return core.E("sqlite.WriteCloser.Close", core.Concat("store failed: ", writer.path), err) } return nil }