github.com/informationsea/shellflow@v0.1.3/filelog.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"compress/zlib"
     6  	"encoding/base64"
     7  	"encoding/json"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"reflect"
    12  	"time"
    13  )
    14  
    15  type FileData []byte
    16  type HashSum []byte
    17  
    18  type FileLog struct {
    19  	Relpath   string
    20  	AbsPath   string
    21  	Size      int64
    22  	Modified  time.Time
    23  	IsDir     bool
    24  	Sha256Sum HashSum
    25  }
    26  
    27  func (v FileLog) String() string {
    28  	return fmt.Sprintf("FileLog{%s, %d}", v.Relpath, v.Size)
    29  }
    30  
    31  // MaximumContentLogSize is maximum size of file that will be saved in log file
    32  const MaximumContentLogSize = 20 * 1024 * 1024 // 20MB
    33  
    34  //var FileLogCache = make(map[string]FileLog)
    35  
    36  func CreateFileLog(files []string, skipSha bool, maximumContentLogSize int64) ([]FileLog, error) {
    37  	fileLogs := make([]FileLog, len(files))
    38  
    39  	for i, v := range files {
    40  		//if cache, ok := FileLogCache[v]; ok {
    41  		//	fileLogs[i] = cache
    42  		//	continue
    43  		//}
    44  
    45  		absPath := Abs(v)
    46  		fileInfo, err := Stat(v)
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  
    51  		hashResult, err := CalcSha256ForFile(v, maximumContentLogSize)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  
    56  		//backupContent := fileInfo.Size() <= maximumContentLogSize
    57  		//var content *bytes.Buffer
    58  		//if backupContent {
    59  		//	content = bytes.NewBuffer(nil)
    60  		//}
    61  		//hash := sha256.New()
    62  		//file, err := os.Open(v)
    63  		//if err != nil {
    64  		//	return nil, err
    65  		//}
    66  		//var reader io.Reader = file
    67  		//if backupContent {
    68  		//	reader = io.TeeReader(file, content)
    69  		//}
    70  		//
    71  		//defer file.Close()
    72  		//io.Copy(hash, reader)
    73  		//
    74  		//contentBytes := []byte{}
    75  		//if backupContent {
    76  		//	contentBytes = content.Bytes()
    77  		//}
    78  
    79  		fileLogs[i] = FileLog{
    80  			Relpath:   v,
    81  			AbsPath:   absPath,
    82  			Size:      fileInfo.Size(),
    83  			Modified:  fileInfo.ModTime(),
    84  			Sha256Sum: hashResult,
    85  		}
    86  
    87  		//FileLogCache[v] = fileLogs[i]
    88  	}
    89  
    90  	return fileLogs, nil
    91  }
    92  
    93  var isChangedCache = make(map[string]bool)
    94  
    95  // IsChanged function check whether the file is changed or not.
    96  // Return true if the file is changed.
    97  // This function does not check SHA256, but only existance and modification date
    98  func (v *FileLog) IsChanged() (bool, error) {
    99  	//if changed, ok := isChangedCache[v.Relpath]; ok {
   100  	//		return changed, nil
   101  	//	}
   102  
   103  	stat, err := Stat(v.Relpath)
   104  	changed := false
   105  	if err != nil && os.IsNotExist(err) {
   106  		changed = true
   107  		return true, nil
   108  	} else if err != nil {
   109  		return true, err
   110  	}
   111  	if stat.ModTime().Unix() != v.Modified.Unix() || stat.ModTime().UnixNano() != v.Modified.UnixNano() || stat.Size() != v.Size {
   112  		changed = true
   113  	}
   114  
   115  	isChangedCache[v.Relpath] = changed
   116  	return changed, nil
   117  }
   118  
   119  func (v HashSum) MarshalJSON() ([]byte, error) {
   120  	return json.Marshal(fmt.Sprintf("%x", v))
   121  }
   122  
   123  func (v FileData) MarshalJSON() ([]byte, error) {
   124  	if v == nil {
   125  		return []byte("null"), nil
   126  	}
   127  
   128  	buf := bytes.NewBuffer(nil)
   129  	encoder := base64.NewEncoder(base64.StdEncoding, buf)
   130  	gzip := zlib.NewWriter(encoder)
   131  	gzip.Write(v)
   132  	gzip.Flush()
   133  	gzip.Close()
   134  	encoder.Close()
   135  
   136  	return json.Marshal(string(buf.Bytes()))
   137  }
   138  
   139  func (v *HashSum) UnmarshalJSON(data []byte) error {
   140  	var str string
   141  	e := json.Unmarshal(data, &str)
   142  	if e != nil {
   143  		return e
   144  	}
   145  	_, e = fmt.Sscanf(str, "%x", v)
   146  	return e
   147  }
   148  
   149  func (v *FileData) UnmarshalJSON(data []byte) error {
   150  	if reflect.DeepEqual(data, []byte("null")) {
   151  		*v = nil
   152  		return nil
   153  	}
   154  
   155  	var str string
   156  	e := json.Unmarshal(data, &str)
   157  	if e != nil {
   158  		return e
   159  	}
   160  	buffer := bytes.NewBuffer([]byte(str))
   161  	decoder := base64.NewDecoder(base64.StdEncoding, buffer)
   162  	gzipReader, err := zlib.NewReader(decoder)
   163  	if err != nil {
   164  		return err
   165  	}
   166  	defer gzipReader.Close()
   167  	*v, err = ioutil.ReadAll(gzipReader)
   168  	return err
   169  }