add concurrency. Closes #5

This commit is contained in:
TJ Holowaychuk
2017-11-19 10:05:09 -08:00
parent f5df8e4fcc
commit fbb44fae1d
2 changed files with 36 additions and 13 deletions
+8 -8
View File
@@ -13,10 +13,10 @@ In your app directory:
```
$ node-prune
files total 25,042
files removed 5,851
size removed 21 MB
duration 433ms
files total 27,330
files removed 3,989
size removed 13 MB
duration 211ms
```
Somewhere else:
@@ -24,10 +24,10 @@ Somewhere else:
```
$ node-prune path/to/node_modules
files total 25,042
files removed 5,851
size removed 21 MB
duration 433ms
files total 27,330
files removed 3,989
size removed 13 MB
duration 211ms
```
## What?
+28 -5
View File
@@ -4,9 +4,9 @@ package prune
import (
"os"
"path/filepath"
"runtime"
"github.com/apex/log"
"github.com/pkg/errors"
)
// DefaultFiles pruned.
@@ -76,6 +76,7 @@ type Pruner struct {
dirs map[string]struct{}
exts map[string]struct{}
files map[string]struct{}
ch chan func()
}
// Option function.
@@ -89,6 +90,7 @@ func New(options ...Option) *Pruner {
exts: toMap(DefaultExtensions),
dirs: toMap(DefaultDirectories),
files: toMap(DefaultFiles),
ch: make(chan func()),
}
for _, o := range options {
@@ -130,6 +132,11 @@ func WithFiles(s []string) Option {
func (p Pruner) Prune() (*Stats, error) {
var stats Stats
for i := 0; i < runtime.NumCPU(); i++ {
go p.start()
}
defer p.stop()
err := filepath.Walk(p.dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
@@ -164,15 +171,19 @@ func (p Pruner) Prune() (*Stats, error) {
// remove and skip dir
if info.IsDir() {
if err := os.RemoveAll(path); err != nil {
return errors.Wrap(err, "removing dir")
p.ch <- func() {
if err := os.RemoveAll(path); err != nil {
ctx.WithError(err).Error("removing directory")
}
}
return filepath.SkipDir
}
// remove file
if err := os.Remove(path); err != nil {
return errors.Wrap(err, "removing")
p.ch <- func() {
if err := os.Remove(path); err != nil {
ctx.WithError(err).Error("removing file")
}
}
return nil
@@ -201,6 +212,18 @@ func (p Pruner) prune(path string, info os.FileInfo) bool {
return ok
}
// start loop.
func (p Pruner) start() {
for fn := range p.ch {
fn()
}
}
// stop loop.
func (p Pruner) stop() {
close(p.ch)
}
// dirStats returns stats for files in dir.
func dirStats(dir string) (*Stats, error) {
var stats Stats