github.com/andy2046/gopie@v0.7.0/pkg/fileutil/fileutil.go (about)

     1  // Package fileutil implements some file utils.
     2  package fileutil
     3  
     4  import (
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"sort"
    10  )
    11  
    12  // ReadDirOperation represents read-directory operation.
    13  type ReadDirOperation struct {
    14  	ext string
    15  }
    16  
    17  const (
    18  	// PrivateFileMode represents file read/write mode to owner.
    19  	PrivateFileMode = 0600
    20  	// PrivateDirMode represents file make/remove mode in the directory to owner.
    21  	PrivateDirMode = 0700
    22  )
    23  
    24  // WithExt filters file names by extension.
    25  func WithExt(ext string) func(*ReadDirOperation) {
    26  	return func(op *ReadDirOperation) { op.ext = ext }
    27  }
    28  
    29  func (op *ReadDirOperation) applyOpts(opts []func(*ReadDirOperation)) {
    30  	for _, opt := range opts {
    31  		opt(op)
    32  	}
    33  }
    34  
    35  // ReadDir returns the file names in the provided directory in order.
    36  func ReadDir(d string, opts ...func(*ReadDirOperation)) ([]string, error) {
    37  	var err error
    38  	op := &ReadDirOperation{}
    39  	op.applyOpts(opts)
    40  
    41  	dir, err := os.Open(d)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	defer dir.Close()
    46  
    47  	names, err := dir.Readdirnames(-1)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	sort.Strings(names)
    52  
    53  	if op.ext != "" {
    54  		temp := make([]string, 0)
    55  		for _, v := range names {
    56  			if filepath.Ext(v) == op.ext {
    57  				temp = append(temp, v)
    58  			}
    59  		}
    60  		names = temp
    61  	}
    62  	return names, nil
    63  }
    64  
    65  // IsDirWriteable checks if dir is writable by writing and removing a file to dir.
    66  func IsDirWriteable(dir string) error {
    67  	f := filepath.Join(dir, ".touch")
    68  	if err := ioutil.WriteFile(f, []byte(""), PrivateFileMode); err != nil {
    69  		return err
    70  	}
    71  	return os.Remove(f)
    72  }
    73  
    74  // TouchDirAll creates directories with 0700 permission if any directory
    75  // does not exist and ensures the provided directory is writable.
    76  func TouchDirAll(dir string) error {
    77  	err := os.MkdirAll(dir, PrivateDirMode)
    78  	if err != nil {
    79  		return err
    80  	}
    81  	return IsDirWriteable(dir)
    82  }
    83  
    84  // CreateDirAll wraps TouchDirAll but returns error
    85  // if the deepest directory is not empty.
    86  func CreateDirAll(dir string) error {
    87  	err := TouchDirAll(dir)
    88  	if err == nil {
    89  		var ns []string
    90  		if ns, err = ReadDir(dir); err != nil {
    91  			return err
    92  		}
    93  		if len(ns) != 0 {
    94  			err = fmt.Errorf("expected %q to be empty, got %q", dir, ns)
    95  		}
    96  	}
    97  	return err
    98  }
    99  
   100  // Exist returns true if a file or directory exists.
   101  func Exist(name string) bool {
   102  	if _, err := os.Stat(name); os.IsNotExist(err) {
   103  		return false
   104  	}
   105  	return true
   106  }