package engine import ( "bytes" "compress/gzip" "crypto/sha256" "encoding/binary" "encoding/hex" "fmt" "os" "strings" "time" "github.com/deranjer/gvc/common/database" ) // CompressIntArray compresses an array of integers into a buffer func CompressIntArray(arry []int64, compressionBuffer *bytes.Buffer) (float64, error) { buf := new(bytes.Buffer) err := binary.Write(buf, binary.LittleEndian, arry) if err != nil { return 0, err } //now compress it compressor := gzip.NewWriter(compressionBuffer) // if err != nil { // fmt.Println("writer level failed to set compression level") // } if _, err := compressor.Write(buf.Bytes()); err != nil { return 0, err } if err := compressor.Close(); err != nil { return 0, err } ratio := float64(len(compressionBuffer.Bytes())) / float64(len(buf.Bytes())) return ratio, nil } // ExpandToIntArray firstly unzips the byte array, then it // converts the byte array back into an int array for use func ExpandToIntArray(length int64, arry []byte, intArray *[]int64) error { buf := bytes.NewBuffer(arry) if reader, err := gzip.NewReader(buf); err != nil { fmt.Println("gzip failed ", err) return err } else { *intArray = make([]int64, length) //you must know the length of the original data if you are to do it this way. err := binary.Read(reader, binary.LittleEndian, intArray) if err != nil { fmt.Println("read failed ", err) } return nil } } // VerifySrcFile checks to see that the file is a regular file // that the OS has meta information about and that can be read by // the os. Currently done in client or server before handing off to engine since some checks don't involve database/manager // func VerifySrcFile(src string) (string, error) { // _, fileName := filepath.Split(src) //dirPath // sourceFileStat, err := os.Stat(src) // if err != nil { // return fileName, errors.New("error on os.Stat " + err.Error()) // } // if !sourceFileStat.Mode().IsRegular() { // return fileName, errors.New("%s is not a regular file" + src) // } // return fileName, nil // } //InitiateDirectory checks all of the directories to make sure they exist func InitiateDirectory(directory string) { // For the keys-folder we need to check if the folder exists... checkDir, err := IsDirectory(directory) if err != nil { fmt.Println("Error checking for "+directory+" directory: %s\r\n", err) panic(err) } if checkDir == true { fmt.Println(directory + " already exists") } else { // Create the directory. fmt.Println("Creating " + directory) err = CreateDirectory(directory) if err != nil { fmt.Println("Error creating the folder %s\r\n", err) panic(err) } } } // CreateInitialCommit copies the files over and compresses them if they are not in the NoCompress struct func CreateInitialCommit(fileList []database.File, commitMessage string) error { // ONLY HAPPENS FOR MASTER I THINK, SO NO BRANCH NEEDED //Need to deduplicate so we aren't storing duplicates of files, storing all the files in one folder won't work, will need something like git //For initial commit no changes are made to files, so don't store anything, just save the list so you can send to server var initialCommit database.Commit initialCommit.Branch = "master" //var hashList [][]byte hasher := sha256.New() for _, file := range fileList { var err error err = file.CalculateHash() if err != nil { return fmt.Errorf("unable to calculate hash for file: %s with error: %s", file.Path, err) } hasher.Write(file.Hash[:]) } time := time.Now() // Adding the metadata to the hash hasher.Write([]byte(commitMessage + time.String())) hashBytes := hasher.Sum(nil) // Getting the hash bytes fullHash := hex.EncodeToString(hashBytes) fmt.Println("Commit hash: ", fullHash) initialCommit.CommitHash = hashBytes return nil } func IsDirectory(path string) (bool, error) { s, err := os.Stat(path) // returns an error if the path does not exist. if err != nil { if os.IsNotExist(err) { return false, nil } return false, err // Different error...? } if s.IsDir() { return true, nil } return false, nil // Redundancy } func CreateDirectory(path string) error { // Assumes checks have been done on if the directory exists... err := os.MkdirAll(path, os.ModePerm) if err != nil { return err } return nil // Redundancy } func DeleteDirectory(path string) error { err := os.RemoveAll(path) return err } //TODO: Most likely can be done with the filepath command so replace this everywhere func StripFilePathBase(pathToFile, base string) string { return strings.Replace(pathToFile, base, "", -1) }