Changing file API

This commit is contained in:
Alex Yatskov 2015-11-01 14:09:46 +09:00
parent 679f2344cb
commit 2c2bda50b2
3 changed files with 34 additions and 143 deletions

96
file.go
View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2015 Alex Yatskov <alex@foosoft.net>
* Author: Alex Yatskov <alex@foosoft.net>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package goldsmith
import (
"bytes"
"os"
)
type file struct {
relPath, srcPath string
meta map[string]interface{}
buff *bytes.Buffer
err error
}
func (f *file) Path() string {
return f.relPath
}
func (f *file) SetPath(path string) {
f.relPath = path
}
func (f *file) Property(key, def string) interface{} {
value, ok := f.meta[key]
if ok {
return value
}
return def
}
func (f *file) SetProperty(key string, value interface{}) {
if f.meta == nil {
f.meta = make(map[string]interface{})
}
f.meta[key] = value
}
func (f *file) Error() error {
return f.err
}
func (f *file) SetError(err error) {
f.err = err
}
func (f *file) Data() []byte {
if f.buff != nil {
return f.buff.Bytes()
}
var buff bytes.Buffer
if len(f.srcPath) > 0 {
file, err := os.Open(f.srcPath)
if err != nil {
f.SetError(err)
return nil
}
defer file.Close()
if _, err := buff.ReadFrom(file); err != nil {
f.SetError(err)
return nil
}
}
f.buff = &buff
return f.buff.Bytes()
}
func (f *file) SetData(data []byte) {
f.buff = bytes.NewBuffer(data)
}

View File

@ -55,17 +55,28 @@ func (gs *goldsmith) scan(srcDir string) {
} }
s := stage{nil, make(chan File, len(matches))} s := stage{nil, make(chan File, len(matches))}
defer close(s.output)
for _, match := range matches { for _, match := range matches {
relPath, err := filepath.Rel(srcDir, match) relPath, err := filepath.Rel(srcDir, match)
if err != nil { if err != nil {
gs.err = err panic(err)
return
} }
s.output <- &file{relPath: relPath, srcPath: match} file := File{
Path: relPath,
Meta: make(map[string]interface{}),
}
var f *os.File
if f, file.Err = os.Open(match); file.Err == nil {
defer f.Close()
_, file.Err = file.Buff.ReadFrom(f)
}
s.output <- file
} }
close(s.output)
gs.stages = append(gs.stages, s) gs.stages = append(gs.stages, s)
} }
@ -82,7 +93,7 @@ func (gs *goldsmith) chainSingle(ts ChainerSingle) {
for file := range s.input { for file := range s.input {
wg.Add(1) wg.Add(1)
go func(f File) { go func(f File) {
s.output <- ts.ChainSingle(gs, f) s.output <- ts.ChainSingle(f)
wg.Done() wg.Done()
}(file) }(file)
} }
@ -95,11 +106,7 @@ func (gs *goldsmith) chainSingle(ts ChainerSingle) {
func (gs *goldsmith) chainMultiple(tm ChainerMultiple) { func (gs *goldsmith) chainMultiple(tm ChainerMultiple) {
s := gs.makeStage() s := gs.makeStage()
tm.ChainMultiple(gs, s.input, s.output) tm.ChainMultiple(s.input, s.output)
}
func (gs *goldsmith) NewFile(relPath string) File {
return &file{relPath: relPath}
} }
func (gs *goldsmith) Chain(chain interface{}, err error) Goldsmith { func (gs *goldsmith) Chain(chain interface{}, err error) Goldsmith {
@ -124,31 +131,20 @@ func (gs *goldsmith) Complete(dstDir string) ([]File, error) {
var files []File var files []File
for file := range s.output { for file := range s.output {
if file.Error() == nil { if file.Err == nil {
data := file.Data() absPath := filepath.Join(dstDir, file.Path)
if data == nil { if file.Err = os.MkdirAll(path.Dir(absPath), 0755); file.Err != nil {
continue continue
} }
absPath := filepath.Join(dstDir, file.Path()) var f *os.File
if err := os.MkdirAll(path.Dir(absPath), 0755); err != nil { if f, file.Err = os.Create(absPath); f == nil {
file.SetError(err) _, file.Err = f.Write(file.Buff.Bytes())
continue f.Close()
}
f, err := os.Create(absPath)
if err != nil {
file.SetError(err)
continue
}
defer f.Close()
if _, err := f.Write(data); err != nil {
file.SetError(err)
continue
} }
} }
file.Buff.Reset()
files = append(files, file) files = append(files, file)
} }

View File

@ -22,33 +22,24 @@
package goldsmith package goldsmith
import "bytes"
type Goldsmith interface { type Goldsmith interface {
Chain(task interface{}, err error) Goldsmith Chain(task interface{}, err error) Goldsmith
Complete(dstDir string) ([]File, error) Complete(dstDir string) ([]File, error)
} }
type ChainerSingle interface { type ChainerSingle interface {
ChainSingle(ctx Context, file File) File ChainSingle(file File) File
} }
type ChainerMultiple interface { type ChainerMultiple interface {
ChainMultiple(ctx Context, input, output chan File) ChainMultiple(input, output chan File)
} }
type Context interface { type File struct {
NewFile(srcDir string) File Path string
} Meta map[string]interface{}
Buff bytes.Buffer
type File interface { Err error
Path() string
SetPath(path string)
Data() []byte
SetData(data []byte)
Property(key, def string) interface{}
SetProperty(key string, value interface{})
Error() error
SetError(err error)
} }