| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 package filesystem |
| 6 |
| 7 import ( |
| 8 "io" |
| 9 "os" |
| 10 "syscall" |
| 11 |
| 12 "github.com/luci/luci-go/common/errors" |
| 13 ) |
| 14 |
| 15 // removeAllImpl removes path and any children it contains. |
| 16 // It removes everything it can but returns the first error |
| 17 // it encounters. If the path does not exist, RemoveAll |
| 18 // returns nil (no error). |
| 19 // |
| 20 // removeAllImpl is a clone of Go's os.RemoveAll which is a wrapper around |
| 21 // os.RemoveAll which uses the supplied removeFunc for deletion. removeFunc is |
| 22 // given a path and an optional os.FileMode (will be nil if absent). |
| 23 // |
| 24 // This was copied from: |
| 25 // https://github.com/golang/go/blob/964639cc338db650ccadeafb7424bc8ebb2c0f6c/sr
c/os/path.go |
| 26 func removeAllImpl(path string, removeFunc func(string, os.FileInfo) error) erro
r { |
| 27 // Simple case: if Remove works, we're done. |
| 28 err := removeFunc(path, nil) |
| 29 if err == nil || IsNotExist(err) { |
| 30 return nil |
| 31 } |
| 32 |
| 33 // Otherwise, is this a directory we need to recurse into? |
| 34 dir, serrWrapped := os.Lstat(path) |
| 35 if serrWrapped != nil { |
| 36 serr := errors.Unwrap(serrWrapped) |
| 37 if serr, ok := serr.(*os.PathError); ok && (IsNotExist(serr.Err)
|| serr.Err == syscall.ENOTDIR) { |
| 38 return nil |
| 39 } |
| 40 return serr |
| 41 } |
| 42 if !dir.IsDir() { |
| 43 // Not a directory; return the error from Remove. |
| 44 return err |
| 45 } |
| 46 |
| 47 // Directory. |
| 48 fd, err := os.Open(path) |
| 49 if err != nil { |
| 50 if IsNotExist(err) { |
| 51 // Race. It was deleted between the Lstat and Open. |
| 52 // Return nil per RemoveAll's docs. |
| 53 return nil |
| 54 } |
| 55 return err |
| 56 } |
| 57 |
| 58 // Remove contents & return first error. |
| 59 err = nil |
| 60 for { |
| 61 names, err1 := fd.Readdirnames(100) |
| 62 for _, name := range names { |
| 63 err1 := removeAllImpl(path+string(os.PathSeparator)+name
, removeFunc) |
| 64 if err == nil { |
| 65 err = err1 |
| 66 } |
| 67 } |
| 68 if err1 == io.EOF { |
| 69 break |
| 70 } |
| 71 // If Readdirnames returned an error, use it. |
| 72 if err == nil { |
| 73 err = err1 |
| 74 } |
| 75 if len(names) == 0 { |
| 76 break |
| 77 } |
| 78 } |
| 79 |
| 80 // Close directory, because windows won't remove opened directory. |
| 81 fd.Close() |
| 82 |
| 83 // Remove directory. |
| 84 err1 := removeFunc(path, dir) |
| 85 if err1 == nil || IsNotExist(err1) { |
| 86 return nil |
| 87 } |
| 88 if err == nil { |
| 89 err = err1 |
| 90 } |
| 91 return err |
| 92 } |
| OLD | NEW |