github.com/qlik-oss/gopherciser@v0.18.6/logger/filewriter.go (about)

     1  package logger
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strconv"
     8  
     9  	"github.com/pkg/errors"
    10  )
    11  
    12  type (
    13  	// Writer simple implementation of a file writer
    14  	Writer struct {
    15  		fil *os.File
    16  	}
    17  )
    18  
    19  // NewWriter create new instance of Writer
    20  func NewWriter(name string) (*Writer, error) {
    21  	w := &Writer{}
    22  
    23  	basePath := filepath.Dir(name)
    24  	if basePath != "." {
    25  		// "." is returned when there's no base path, hence no directory
    26  		// needs to be created in advance
    27  		if err := os.MkdirAll(basePath, os.ModePerm); err != nil {
    28  			return nil, errors.Wrapf(err, "failed to create base folder <%s>", basePath)
    29  		}
    30  	}
    31  
    32  	if err := w.createFile(name); err != nil {
    33  		return nil, errors.Wrapf(err, "failed to create file<%s>", name)
    34  	}
    35  	return w, nil
    36  }
    37  
    38  // Write implement io.Writer interface
    39  func (w Writer) Write(p []byte) (int, error) {
    40  	if w.fil == nil {
    41  		return 0, nil
    42  	}
    43  
    44  	n, err := w.fil.Write(p)
    45  	if err != nil {
    46  		return n, errors.WithStack(err)
    47  	}
    48  
    49  	return n, nil
    50  }
    51  
    52  func (w *Writer) createFile(name string) error {
    53  	if fileExists(name) {
    54  		name = backupName(name)
    55  	}
    56  
    57  	fil, err := os.Create(name)
    58  	if err != nil {
    59  		return errors.Wrapf(err, "Failed to create log file<%s>", name)
    60  	}
    61  
    62  	w.fil = fil
    63  	return nil
    64  }
    65  
    66  // Close writer
    67  func (w *Writer) Close() error {
    68  	if w.fil == nil {
    69  		return nil
    70  	}
    71  
    72  	return errors.WithStack(w.fil.Close())
    73  }
    74  
    75  func backupName(name string) string {
    76  	if fileExists(name) {
    77  		return backupName(addDashEnd(name))
    78  	}
    79  	return name
    80  }
    81  
    82  func fileExists(name string) bool {
    83  	if _, err := os.Stat(name); !os.IsNotExist(err) {
    84  		return true
    85  	}
    86  	return false
    87  }
    88  
    89  func addDashEnd(name string) string {
    90  	num := "-001"
    91  
    92  	ext := filepath.Ext(name)
    93  	runes := []rune(name[0:(len(name) - len(ext))])
    94  
    95  	if len(name) > 4 && len(runes) > 3 && runes[len(runes)-4] == '-' {
    96  		cNum := runes[len(runes)-3:]
    97  		if cInt, err := strconv.Atoi(string(cNum)); err == nil { //else is not number, keep num
    98  			runes = runes[0:(len(runes) - 4)] //Remove current dash numbering
    99  			cInt++
   100  			num = fmt.Sprintf("-%0.3d", cInt)
   101  		}
   102  	}
   103  
   104  	return fmt.Sprintf("%s%s%s", string(runes), num, ext)
   105  }