| @ -0,0 +1,143 @@ | |||||
| package Database | |||||
| import ( | |||||
| "database/sql" | |||||
| "fmt" | |||||
| "time" | |||||
| ) | |||||
| type FilesystemHashRow struct { | |||||
| Path string | |||||
| Hash string | |||||
| UpdatedAt time.Time | |||||
| } | |||||
| func FindOrCreateFileHash(rows []FilesystemHashRow) error { | |||||
| var ( | |||||
| stmtString string | |||||
| stmt *sql.Stmt | |||||
| values []interface{} = []interface{}{} | |||||
| e error | |||||
| ) | |||||
| stmtString = "INSERT OR REPLACE INTO filesystem_hash (id, path, hash, updated_at) VALUES " | |||||
| for _, row := range rows { | |||||
| stmtString += `( | |||||
| (SELECT id FROM filesystem_hash WHERE path = ?), | |||||
| ?, | |||||
| ?, | |||||
| ? | |||||
| ),` | |||||
| values = append(values, row.Path, row.Path, row.Hash, row.UpdatedAt.String()) | |||||
| } | |||||
| stmtString = stmtString[0 : len(stmtString)-1] | |||||
| stmt, e = DB.Prepare(stmtString) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| _, e = stmt.Exec(values...) | |||||
| return e | |||||
| } | |||||
| func FindModifiedFiles(hashes []string) ([]string, error) { | |||||
| var ( | |||||
| stmtString string | |||||
| stmt *sql.Stmt | |||||
| values []interface{} = []interface{}{} | |||||
| result *sql.Rows | |||||
| dirtyFiles []string = []string{} | |||||
| e error | |||||
| ) | |||||
| stmtString = "SELECT id, path FROM filesystem_hash WHERE hash NOT IN (" | |||||
| for _, row := range hashes { | |||||
| stmtString += "?," | |||||
| values = append(values, row) | |||||
| } | |||||
| stmtString = stmtString[0:len(stmtString)-1] + ")" | |||||
| stmt, e = DB.Prepare(stmtString) | |||||
| if e != nil { | |||||
| return dirtyFiles, e | |||||
| } | |||||
| result, e = stmt.Query(values...) | |||||
| if e != nil { | |||||
| return dirtyFiles, e | |||||
| } | |||||
| defer result.Close() | |||||
| for result.Next() { | |||||
| var id string | |||||
| var hash string | |||||
| e = result.Scan(&id, &hash) | |||||
| if e != nil { | |||||
| return dirtyFiles, e | |||||
| } | |||||
| fmt.Println(id, hash) | |||||
| dirtyFiles = append(dirtyFiles, hash) | |||||
| } | |||||
| e = result.Err() | |||||
| return dirtyFiles, e | |||||
| } | |||||
| /* | |||||
| func FindNewFiles(files []string) ([]string, error) { | |||||
| var ( | |||||
| stmtString string | |||||
| stmt *sql.Stmt | |||||
| values []interface{} = []interface{}{} | |||||
| result *sql.Rows | |||||
| dirtyFiles []string = []string{} | |||||
| e error | |||||
| ) | |||||
| stmtString = `select * | |||||
| from ( | |||||
| values (4),(5),(6) | |||||
| ) as v(id) | |||||
| where not exists (select * | |||||
| from images i | |||||
| where i.id = v.id);` | |||||
| for _, row := range hashes { | |||||
| stmtString += "?," | |||||
| values = append(values, row) | |||||
| } | |||||
| stmtString = stmtString[0:len(stmtString)-1] + ")" | |||||
| stmt, e = DB.Prepare(stmtString) | |||||
| if e != nil { | |||||
| return dirtyFiles, e | |||||
| } | |||||
| result, e = stmt.Query(values...) | |||||
| if e != nil { | |||||
| return dirtyFiles, e | |||||
| } | |||||
| defer result.Close() | |||||
| for result.Next() { | |||||
| var id string | |||||
| var hash string | |||||
| e = result.Scan(&id, &hash) | |||||
| if e != nil { | |||||
| return dirtyFiles, e | |||||
| } | |||||
| fmt.Println(id, hash) | |||||
| dirtyFiles = append(dirtyFiles, hash) | |||||
| } | |||||
| e = result.Err() | |||||
| return dirtyFiles, e | |||||
| } | |||||
| */ | |||||
| @ -0,0 +1,128 @@ | |||||
| package Filesystem | |||||
| import ( | |||||
| "PackageManager/Client/Database" | |||||
| "crypto/md5" | |||||
| "fmt" | |||||
| "io/ioutil" | |||||
| "os" | |||||
| "path/filepath" | |||||
| "strings" | |||||
| ) | |||||
| func HashFile(path string) (string, error) { | |||||
| var ( | |||||
| Md5Hash string | |||||
| hashBytes [16]byte | |||||
| file *os.File | |||||
| e error | |||||
| ) | |||||
| file, e = os.Open(path) | |||||
| if e != nil { | |||||
| panic(e) | |||||
| } | |||||
| defer file.Close() | |||||
| body, e := ioutil.ReadAll(file) | |||||
| if e != nil { | |||||
| panic(e) | |||||
| } | |||||
| //Get the 16 bytes hash | |||||
| hashBytes = md5.Sum(body) | |||||
| //Convert the bytes to a string | |||||
| Md5Hash = fmt.Sprintf("%x", hashBytes) | |||||
| return Md5Hash, nil | |||||
| } | |||||
| func UpdateFilesystemHash() error { | |||||
| var ( | |||||
| fileHash string | |||||
| rows []Database.FilesystemHashRow | |||||
| e error | |||||
| ) | |||||
| e = filepath.Walk(".", func(path string, info os.FileInfo, e error) error { | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| // Ignore hidden files | |||||
| if strings.HasPrefix(info.Name(), ".") || strings.HasPrefix(path, ".") { | |||||
| return nil | |||||
| } | |||||
| // Ignore directories | |||||
| if info.IsDir() { | |||||
| return nil | |||||
| } | |||||
| fileHash, e = HashFile(path) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| rows = append(rows, Database.FilesystemHashRow{ | |||||
| Path: path, | |||||
| Hash: fileHash, | |||||
| UpdatedAt: info.ModTime(), | |||||
| }) | |||||
| // TODO: If len(rows) > x, update the db and clear out rows, and continue | |||||
| return nil | |||||
| }) | |||||
| if e != nil { | |||||
| panic(e) | |||||
| } | |||||
| return Database.FindOrCreateFileHash(rows) | |||||
| } | |||||
| func GetFilesystemDiff() error { | |||||
| var ( | |||||
| fileHash string | |||||
| hashes []string = []string{} | |||||
| e error | |||||
| ) | |||||
| e = filepath.Walk(".", func(path string, info os.FileInfo, e error) error { | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| // Ignore hidden files | |||||
| if strings.HasPrefix(info.Name(), ".") || strings.HasPrefix(path, ".") { | |||||
| return nil | |||||
| } | |||||
| // Ignore directories | |||||
| if info.IsDir() { | |||||
| return nil | |||||
| } | |||||
| fileHash, e = HashFile(path) | |||||
| if e != nil { | |||||
| return e | |||||
| } | |||||
| hashes = append(hashes, fileHash) | |||||
| // TODO: If len(rows) > x, update the db and clear out rows, and continue | |||||
| return nil | |||||
| }) | |||||
| dirty, e := Database.FindModifiedFiles(hashes) | |||||
| fmt.Println(dirty) | |||||
| return e | |||||
| } | |||||
| @ -1,13 +1,31 @@ | |||||
| package main | package main | ||||
| import ( | import ( | ||||
| "fmt" | |||||
| "PackageManager/Archive" | |||||
| "PackageManager/Client/Database" | |||||
| "PackageManager/Client/Filesystem" | |||||
| ) | ) | ||||
| func main() { | func main() { | ||||
| var e error | |||||
| e = Database.InitDB() | |||||
| if e != nil { | |||||
| panic(e) | |||||
| } | |||||
| /* | |||||
| e = Filesystem.UpdateFilesystemHash() | |||||
| if e != nil { | |||||
| panic(e) | |||||
| } | |||||
| */ | |||||
| e = Filesystem.GetFilesystemDiff() | |||||
| if e != nil { | |||||
| panic(e) | |||||
| } | |||||
| //e := Archive.TarGzip("/tmp/test", "/tmp/test.tar.gz") | //e := Archive.TarGzip("/tmp/test", "/tmp/test.tar.gz") | ||||
| e := Archive.UntarGzip("/tmp/test.tar.gz", "/tmp/test") | |||||
| fmt.Println(e) | |||||
| //e := Archive.UntarGzip("/tmp/test.tar.gz", "/tmp/test") | |||||
| //fmt.Println(e) | |||||
| } | } | ||||
| @ -0,0 +1,5 @@ | |||||
| package Variables | |||||
| const ( | |||||
| DatabaseName string = "package_manager.db" | |||||
| ) | |||||