@ -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 | |||
import ( | |||
"fmt" | |||
"PackageManager/Archive" | |||
"PackageManager/Client/Database" | |||
"PackageManager/Client/Filesystem" | |||
) | |||
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.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" | |||
) |