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 }