diff --git a/.gitignore b/.gitignore index 4762cbb..8b84a56 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.db *.tar *.tar.gz +tjpkg diff --git a/Client/Database/Filesystem.go b/Client/Database/Filesystem.go deleted file mode 100644 index 11b56eb..0000000 --- a/Client/Database/Filesystem.go +++ /dev/null @@ -1,114 +0,0 @@ -package Database - -import ( - "database/sql" - "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.Unix()) - } - - 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) (map[int]string, error) { - var ( - stmtString string - stmt *sql.Stmt - values []interface{} = []interface{}{} - result *sql.Rows - dirtyFiles map[int]string = make(map[int]string) - counter int = 0 - 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 path string - e = result.Scan(&id, &path) - if e != nil { - return dirtyFiles, e - } - dirtyFiles[counter] = path - counter++ - } - - e = result.Err() - return dirtyFiles, e -} - -func GetMostRecentTimestamp() (time.Time, error) { - var ( - stmt *sql.Stmt - result *sql.Row - lastUpdatedAt int64 - e error - ) - - stmt, e = DB.Prepare(` - SELECT updated_at FROM filesystem_hash - ORDER BY updated_at DESC - LIMIT 1; - `) - if e != nil { - return time.Now(), e - } - - result = stmt.QueryRow() - - result.Scan(&lastUpdatedAt) - - return time.Unix(lastUpdatedAt, 0), nil -} diff --git a/Client/Database/Init.go b/Client/Database/Init.go index 98b2596..7f199a4 100644 --- a/Client/Database/Init.go +++ b/Client/Database/Init.go @@ -2,41 +2,59 @@ package Database import ( "database/sql" + "time" _ "github.com/mattn/go-sqlite3" + bolt "go.etcd.io/bbolt" "PackageManager/Variables" ) var ( - DB *sql.DB + DB *sql.DB + FsDB *bolt.DB ) func init() { var e error + // Initialise sqlite3 database for package versioning DB, e = sql.Open("sqlite3", Variables.DatabaseName) if e != nil { panic(e) } + + // Initialise bolt db for filesystem hashing + FsDB, e = bolt.Open(Variables.FsHashDatabaseName, 0600, &bolt.Options{ + Timeout: 5 * time.Second, + }) + if e != nil { + panic(e) + } } func InitDB() error { var ( - sqlStmt string - e error + tx *bolt.Tx + e error ) - sqlStmt = ` - CREATE TABLE IF NOT EXISTS filesystem_hash ( - id INTEGER NOT NULL PRIMARY KEY, - path VARCHAR(256), - hash VARCHAR(64), - created_at INTEGER DEFAULT CURRENT_TIMESTAMP, - updated_at INTEGER - ) - ` - _, e = DB.Exec(sqlStmt) + + tx, e = FsDB.Begin(true) + if e != nil { + return e + } + defer tx.Rollback() + + _, e = tx.CreateBucketIfNotExists(Variables.FsHashIndexBucket) + if e != nil { + return e + } + + _, e = tx.CreateBucketIfNotExists(Variables.FsHashPicksBucket) if e != nil { return e } - return nil + + e = tx.Commit() + + return e } diff --git a/Client/Filesystem/CommitFiles.go b/Client/Filesystem/CommitFiles.go new file mode 100644 index 0000000..5886fce --- /dev/null +++ b/Client/Filesystem/CommitFiles.go @@ -0,0 +1,48 @@ +package Filesystem + +import ( + "PackageManager/Client/Database" + "PackageManager/Variables" + "fmt" + + bolt "go.etcd.io/bbolt" +) + +func CommitFiles() error { + var ( + fsStatus FilesystemStatus + indexBucket *bolt.Bucket + f string + e error + ) + + fsStatus, e = GetFilesystemDiff(Variables.RootDir) + if e != nil { + return e + } + + e = Database.FsDB.Batch(func(tx *bolt.Tx) error { + indexBucket = tx.Bucket(Variables.FsHashIndexBucket) + + if len(fsStatus.PickedFiles) > 0 { + for _, f = range fsStatus.PickedFiles { + fmt.Println(f) + e = AddFileToBucket(indexBucket, f) + if e != nil { + return e + } + } + + /* + e = tx.DeleteBucket(Variables.FsHashPicksBucket) + if e != nil { + return e + } + */ + } + + return nil + }) + + return e +} diff --git a/Client/Filesystem/Config.go b/Client/Filesystem/Config.go new file mode 100644 index 0000000..fb192c2 --- /dev/null +++ b/Client/Filesystem/Config.go @@ -0,0 +1,77 @@ +package Filesystem + +import ( + "crypto/sha1" + "regexp" + + "PackageManager/Variables" +) + +var ( + sha1Hash = sha1.New() + + PruneRegex []*regexp.Regexp + IgnoreRegex []*regexp.Regexp +) + +func init() { + var e error + + e = InitPruneRegex() + if e != nil { + panic(e) + } + + e = InitIgnoreRegex() + if e != nil { + panic(e) + } +} + +func InitPruneRegex() error { + var ( + r *regexp.Regexp + s string + e error + ) + + for _, s = range Variables.PruneRegexPaths { + r, e = regexp.Compile(s) + if e != nil { + return e + } + PruneRegex = append(PruneRegex, r) + } + return nil +} + +func InitIgnoreRegex() error { + var ( + r *regexp.Regexp + s string + e error + ) + + for _, s = range Variables.IgnoreRegexPaths { + r, e = regexp.Compile(s) + if e != nil { + return e + } + IgnoreRegex = append(IgnoreRegex, r) + } + return nil +} + +func matchAny(p string, a []*regexp.Regexp) bool { + var ( + regex *regexp.Regexp + match bool + ) + for _, regex = range a { + match = regex.MatchString(p) + if match == true { + return true + } + } + return false +} diff --git a/Client/Filesystem/FileObject.go b/Client/Filesystem/FileObject.go new file mode 100644 index 0000000..b7c498b --- /dev/null +++ b/Client/Filesystem/FileObject.go @@ -0,0 +1,211 @@ +package Filesystem + +import ( + "bytes" + "encoding/gob" + "encoding/hex" + "errors" + "fmt" + "io" + "os" + "path/filepath" +) + +var ( + // TODO: Where do I put this + Data string +) + +type Package struct { + Name string + Version string +} + +type FileObject struct { + FileMode os.FileMode + Size int64 + Package Package + Ref string + Sha1 []byte +} + +type ByName []Package + +func (f FileObject) IsLink() bool { + return f.FileMode&os.ModeSymlink != 0 +} + +func (f FileObject) objFile() string { + return filepath.Join(f.objDir(), hex.EncodeToString(f.Sha1)) +} + +func (f FileObject) objDir() string { + return filepath.Join(Data, hex.EncodeToString(f.Sha1[:2])) +} + +func (f FileObject) Reset(dst string) error { + var e error + + if f.IsLink() { + _, e = os.Lstat(dst) + if !os.IsNotExist(e) { + e = os.Remove(dst) + if e != nil { + return e + } + } + + e = os.Symlink(f.Ref, dst) + if e != nil { + return e + } + + return nil + } + + f.cp(f.objFile(), dst) + e = os.Chmod(dst, f.FileMode) + if e != nil { + return e + } + + return nil +} + +func (f FileObject) Stov(src string) error { + var e error + + if f.IsLink() { + return nil + } + + e = os.MkdirAll(f.objDir(), 0744) + if e != nil { + return e + } + + f.cp(src, f.objFile()) + return nil +} + +func (f FileObject) cp(src string, dst string) error { + var ( + srcFile, dstFile *os.File + e error + ) + + fmt.Println("cp ", src, dst) + + srcFile, e = os.Open(src) + if e != nil { + return e + } + defer srcFile.Close() + + dstFile, e = os.Create(dst) + if e != nil { + return e + } + defer dstFile.Close() + + _, e = io.Copy(dstFile, srcFile) + if e != nil { + return e + } + + return dstFile.Sync() +} + +func (f FileObject) IsDifferent(fn FileObject) error { + if f.FileMode != fn.FileMode { + return errors.New("Mode does not match") + } + + if f.IsLink() { + if f.Ref != fn.Ref { + return errors.New("Ref does not match") + } + return nil + } + + if f.Size != fn.Size { + return errors.New("Size does not match") + } + + if bytes.Compare(f.Sha1, fn.Sha1) != 0 { + return errors.New("Sha1 does not match") + } + + return nil +} + +func CreateFileObject(f string) (FileObject, error) { + var ( + fo FileObject + fi os.FileInfo + file *os.File + e error + ) + + fi, e = os.Lstat(f) + if e != nil { + return fo, e + } + + fo = FileObject{ + FileMode: fi.Mode(), + Size: fi.Size(), + } + + if fo.IsLink() { + fo.Ref, e = os.Readlink(f) + if e != nil { + return fo, e + } + return fo, nil + + } + + file, e = os.Open(f) + if e != nil { + return fo, e + } + defer file.Close() + + io.Copy(sha1Hash, file) + fo.Sha1 = sha1Hash.Sum(nil) + + return fo, nil +} + +func (f FileObject) ToBytes() ([]byte, error) { + var ( + encoder *gob.Encoder + buf bytes.Buffer + e error + ) + + encoder = gob.NewEncoder(&buf) + e = encoder.Encode(f) + return buf.Bytes(), e +} + +func FromBytes(v []byte) (FileObject, error) { + var ( + buf *bytes.Buffer + decoder *gob.Decoder + fo FileObject + e error + ) + + buf = bytes.NewBuffer(v) + + decoder = gob.NewDecoder(buf) + + e = decoder.Decode(&fo) + if e != nil { + return fo, e + } + + return fo, nil +} diff --git a/Client/Filesystem/FilesystemDiff.go b/Client/Filesystem/FilesystemDiff.go new file mode 100644 index 0000000..9f49260 --- /dev/null +++ b/Client/Filesystem/FilesystemDiff.go @@ -0,0 +1,171 @@ +package Filesystem + +import ( + "PackageManager/Client/Database" + "PackageManager/Variables" + "fmt" + "log" + "os" + "path/filepath" + + bolt "go.etcd.io/bbolt" +) + +type FilesystemStatus struct { + NewFiles []string + PickedFiles []string + ModifiedFiles []string + MissingFiles []string +} + +func ShowFilesystemDiff(root string) error { + var ( + fsStatus FilesystemStatus + //f string + e error + ) + + fsStatus, e = GetFilesystemDiff(root) + if e != nil { + return e + } + + if len(fsStatus.NewFiles) > 0 { + fmt.Printf("New files: %d\n", len(fsStatus.NewFiles)) + /* + fmt.Println("New files:") + for _, f = range fsStatus.NewFiles { + fmt.Printf("\t%s\n", Color.Green(f)) + } + */ + } + + if len(fsStatus.PickedFiles) > 0 { + fmt.Printf("Picked files: %d\n", len(fsStatus.PickedFiles)) + /* + fmt.Println("Added files:") + for _, f = range fsStatus.PickedFiles { + fmt.Printf("\t%s\n", Color.Green(f)) + } + */ + } + + if len(fsStatus.ModifiedFiles) > 0 { + fmt.Printf("Modified files: %d\n", len(fsStatus.ModifiedFiles)) + /* + fmt.Println("Modified files:") + for _, f = range fsStatus.ModifiedFiles { + fmt.Printf("\t%s\n", Color.Green(f)) + } + */ + } + + if len(fsStatus.MissingFiles) > 0 { + fmt.Printf("Modified files: %d\n", len(fsStatus.MissingFiles)) + /* + fmt.Println("Deleted files:") + for _, f = range fsStatus.MissingFiles { + fmt.Printf("\t%s\n", Color.Green(f)) + } + */ + } + + return nil +} + +func GetFilesystemDiff(root string) (FilesystemStatus, error) { + var ( + fsStatus FilesystemStatus = FilesystemStatus{} + + rootStat os.FileInfo + + picksBucket *bolt.Bucket + indexBucket *bolt.Bucket + + pick, known []byte + + newFileObject FileObject + knownFileObject FileObject + + e error + ) + + rootStat, e = os.Stat(root) + if e != nil { + return fsStatus, e + } + + if rootStat.IsDir() && root[len(root)-1:] != "/" { + root = root + "/" + } + + e = Database.FsDB.View(func(tx *bolt.Tx) error { + + picksBucket = tx.Bucket(Variables.FsHashPicksBucket) + indexBucket = tx.Bucket(Variables.FsHashPicksBucket) + + filepath.Walk(root, func(p string, i os.FileInfo, _ error) error { + + // Ignore path in Variables.PruneRegexPaths + if i.IsDir() && matchAny(p, PruneRegex) { + log.Println("Prune", p) + return filepath.SkipDir + } + + // Ignore path in Variables.IgnoreRegexPaths + if matchAny(p, IgnoreRegex) { + return nil + } + + if !i.Mode().IsRegular() && (i.Mode()&os.ModeSymlink == 0) { + return nil + } + + pick = picksBucket.Get([]byte(p)) + known = indexBucket.Get([]byte(p)) + + if pick != nil { + fsStatus.PickedFiles = append(fsStatus.PickedFiles, p) + return nil + } + + if known != nil { + newFileObject, e = CreateFileObject(p) + if os.IsNotExist(e) { + return nil + } + if e != nil { + return e + } + + knownFileObject, e = FromBytes(known) + if e != nil { + return e + } + + e = newFileObject.IsDifferent(knownFileObject) + if e != nil { + fsStatus.ModifiedFiles = append(fsStatus.ModifiedFiles, p) + } + + return nil + } + + fsStatus.NewFiles = append(fsStatus.NewFiles, p) + + return nil + }) + + indexBucket.ForEach(func(k, v []byte) error { + _, e = os.Lstat(string(k)) + if os.IsNotExist(e) { + fsStatus.MissingFiles = append(fsStatus.MissingFiles, string(k)) + } + return nil + }) + + return nil + }) + + return fsStatus, e +} diff --git a/Client/Filesystem/HashFilesystem.go b/Client/Filesystem/HashFilesystem.go deleted file mode 100644 index 2a00261..0000000 --- a/Client/Filesystem/HashFilesystem.go +++ /dev/null @@ -1,170 +0,0 @@ -package Filesystem - -import ( - "PackageManager/Client/Database" - "PackageManager/Variables" - "crypto/md5" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -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 - dir string - e error - ) - - for _, dir = range Variables.InstallDirs { - _, e = os.Stat(dir) - if os.IsNotExist(e) { - continue - } - e = filepath.Walk(dir, 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() (map[int]string, map[int]string, error) { - var ( - fileHash string - hashes []string = []string{} - lastUpdatedAt time.Time - dirtyFiles map[int]string - newFiles map[int]string = make(map[int]string) - newFilesTmp map[string]string = make(map[string]string) - counter int - ok bool - e error - ) - - lastUpdatedAt, e = Database.GetMostRecentTimestamp() - if e != nil { - return dirtyFiles, newFiles, e - } - - 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) - - if info.ModTime().After(lastUpdatedAt) { - newFilesTmp[path] = path - } - - // TODO: If len(rows) > x, update the db and clear out rows, and continue - - return nil - }) - if e != nil { - return dirtyFiles, newFiles, e - } - - dirtyFiles, e = Database.FindModifiedFiles(hashes) - if e != nil { - return dirtyFiles, newFiles, e - } - - for _, file := range dirtyFiles { - _, ok = newFilesTmp[file] - if ok { - delete(newFilesTmp, file) - } - } - - counter = len(dirtyFiles) - - for _, file := range newFilesTmp { - newFiles[counter] = file - counter++ - } - - return dirtyFiles, newFiles, e -} diff --git a/Client/Filesystem/ManageFileBucket.go b/Client/Filesystem/ManageFileBucket.go new file mode 100644 index 0000000..8cd907e --- /dev/null +++ b/Client/Filesystem/ManageFileBucket.go @@ -0,0 +1,31 @@ +package Filesystem + +import ( + "os" + + bolt "go.etcd.io/bbolt" +) + +func AddFileToBucket(bucket *bolt.Bucket, filePath string) error { + var ( + fileObject FileObject + fileObjectBytes []byte + e error + ) + fileObject, e = CreateFileObject(filePath) + if os.IsNotExist(e) { + return nil + } + if e != nil { + return e + } + fileObjectBytes, e = fileObject.ToBytes() + if e != nil { + return e + } + return bucket.Put([]byte(filePath), fileObjectBytes) +} + +func RemoveFileFromBucket(bucket *bolt.Bucket, filePath string) error { + return bucket.Delete([]byte(filePath)) +} diff --git a/Client/Filesystem/PickFiles.go b/Client/Filesystem/PickFiles.go new file mode 100644 index 0000000..1c31779 --- /dev/null +++ b/Client/Filesystem/PickFiles.go @@ -0,0 +1,88 @@ +package Filesystem + +import ( + "PackageManager/Client/Database" + "PackageManager/Variables" + + bolt "go.etcd.io/bbolt" +) + +func PickFiles(rootPath string) error { + var ( + fsStatus FilesystemStatus + picksBucket *bolt.Bucket + f string + e error + ) + + fsStatus, e = GetFilesystemDiff(rootPath) + if e != nil { + return e + } + + e = Database.FsDB.Batch(func(tx *bolt.Tx) error { + picksBucket = tx.Bucket(Variables.FsHashPicksBucket) + + if len(fsStatus.NewFiles) > 0 { + for _, f = range fsStatus.NewFiles { + e = AddFileToBucket(picksBucket, f) + if e != nil { + return e + } + } + } + + if len(fsStatus.ModifiedFiles) > 0 { + for _, f = range fsStatus.NewFiles { + e = AddFileToBucket(picksBucket, f) + if e != nil { + return e + } + } + } + + if len(fsStatus.MissingFiles) > 0 { + for _, f = range fsStatus.NewFiles { + e = RemoveFileFromBucket(picksBucket, f) + if e != nil { + return e + } + } + } + + return nil + }) + + return e +} + +func ResetAllPickedFiles() error { + var ( + fsStatus FilesystemStatus + picksBucket *bolt.Bucket + f string + e error + ) + + fsStatus, e = GetFilesystemDiff(Variables.RootDir) + if e != nil { + return e + } + + e = Database.FsDB.Batch(func(tx *bolt.Tx) error { + picksBucket = tx.Bucket(Variables.FsHashPicksBucket) + + if len(fsStatus.PickedFiles) > 0 { + for _, f = range fsStatus.PickedFiles { + e = RemoveFileFromBucket(picksBucket, f) + if e != nil { + return e + } + } + } + + return nil + }) + + return e +} diff --git a/Client/Package/CreatePackage.go b/Client/Package/CreatePackage.go index 26e49b3..6da7a3a 100644 --- a/Client/Package/CreatePackage.go +++ b/Client/Package/CreatePackage.go @@ -1,145 +1,134 @@ package Package -import ( - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "strings" - - "PackageManager/Archive" - "PackageManager/Client/Filesystem" - "PackageManager/Color" - "PackageManager/Helper" -) - func CreatePackage() error { - var ( - dirtyFiles map[int]string - newFiles map[int]string - pkgFiles map[int]string = make(map[int]string) - choices string - choicesSplit []string - filePath string - pkgName string - pkgVersion string - pkgNameVersion string - tmpDir string - index int - ok bool - e error - ) - - fmt.Println("Initialising package creation...") - - dirtyFiles, newFiles, e = Filesystem.GetFilesystemDiff() - if e != nil { - return e - } - - fmt.Println("\nModified files...") - for i, file := range dirtyFiles { - fmt.Printf( - "\t%d - %s\n", - i, - Color.Red(file), - ) - } + return nil - fmt.Println("\nNew files...") - for i, file := range newFiles { - fmt.Printf( - "\t%d - %s\n", - i, - Color.Red(file), + /* + var ( + dirtyFiles map[int]string + newFiles map[int]string + pkgFiles map[int]string = make(map[int]string) + choices string + choicesSplit []string + filePath string + pkgName string + pkgVersion string + pkgNameVersion string + tmpDir string + index int + ok bool + e error ) - } - fmt.Println("Please select the files you would like to use to create the package. Leave empty for all.") - choices = Helper.Input() + fmt.Println("Initialising package creation...") + + dirtyFiles, newFiles, e = Filesystem.GetFilesystemDiff() + if e != nil { + return e + } - if choices == "" { + fmt.Println("\nModified files...") for i, file := range dirtyFiles { - pkgFiles[i] = file + fmt.Printf( + "\t%d - %s\n", + i, + Color.Red(file), + ) } + + fmt.Println("\nNew files...") for i, file := range newFiles { - pkgFiles[i] = file + fmt.Printf( + "\t%d - %s\n", + i, + Color.Red(file), + ) } - } else { - choicesSplit = strings.Split(choices, ",") + fmt.Println("Please select the files you would like to use to create the package. Leave empty for all.") + choices = Helper.Input() - for _, i := range choicesSplit { - index, e = strconv.Atoi(i) - if e != nil { - // TODO: Handle this error - panic(e) + if choices == "" { + for i, file := range dirtyFiles { + pkgFiles[i] = file + } + for i, file := range newFiles { + pkgFiles[i] = file } - filePath, ok = dirtyFiles[index] - if !ok { - filePath, ok = newFiles[index] + } else { + + choicesSplit = strings.Split(choices, ",") + + for _, i := range choicesSplit { + index, e = strconv.Atoi(i) + if e != nil { + // TODO: Handle this error + panic(e) + } + filePath, ok = dirtyFiles[index] if !ok { - return errors.New("Invalid package selection") + filePath, ok = newFiles[index] + if !ok { + return errors.New("Invalid package selection") + } } + pkgFiles[index] = filePath } - pkgFiles[index] = filePath } - } - fmt.Println("Please enter the package name:") - pkgName = Helper.Input() - if pkgName == "" { - return errors.New("Invalid package name") - } + fmt.Println("Please enter the package name:") + pkgName = Helper.Input() + if pkgName == "" { + return errors.New("Invalid package name") + } - fmt.Println("Please enter the package version:") - pkgVersion = Helper.Input() - if pkgVersion == "" { - return errors.New("Invalid package name") - } + fmt.Println("Please enter the package version:") + pkgVersion = Helper.Input() + if pkgVersion == "" { + return errors.New("Invalid package name") + } - fmt.Printf("Package Name: %s\n", pkgName) - fmt.Printf("Package Version: %s\n", pkgVersion) + fmt.Printf("Package Name: %s\n", pkgName) + fmt.Printf("Package Version: %s\n", pkgVersion) - fmt.Println("Files to be added") - for i, file := range pkgFiles { - fmt.Printf( - "\t%d - %s\n", - i, - Color.Green(file), - ) - } + fmt.Println("Files to be added") + for i, file := range pkgFiles { + fmt.Printf( + "\t%d - %s\n", + i, + Color.Green(file), + ) + } - fmt.Println("Is this correct? [y/N]") - if strings.ToLower(Helper.Input()) != "y" { - return errors.New("User aborted") - } + fmt.Println("Is this correct? [y/N]") + if strings.ToLower(Helper.Input()) != "y" { + return errors.New("User aborted") + } - pkgNameVersion = fmt.Sprintf("%s-%s", pkgName, pkgVersion) + pkgNameVersion = fmt.Sprintf("%s-%s", pkgName, pkgVersion) - tmpDir, e = ioutil.TempDir("/tmp", pkgNameVersion) - if e != nil { - return e - } - defer os.RemoveAll(tmpDir) + tmpDir, e = ioutil.TempDir("/tmp", pkgNameVersion) + if e != nil { + return e + } + defer os.RemoveAll(tmpDir) - for _, file := range pkgFiles { - Filesystem.CopyFile(file, filepath.Join(tmpDir, file)) - } + for _, file := range pkgFiles { + Filesystem.CopyFile(file, filepath.Join(tmpDir, file)) + } - // TODO: Add dependancy management here + // TODO: Add dependancy management here - e = Archive.TarGzip(tmpDir, pkgNameVersion+".tar.gz") - if e != nil { - return e - } + e = Archive.TarGzip(tmpDir, pkgNameVersion+".tar.gz") + if e != nil { + return e + } - fmt.Printf( - Color.Green("\nSuccessfully created package %s\n"), - pkgNameVersion, - ) + fmt.Printf( + Color.Green("\nSuccessfully created package %s\n"), + pkgNameVersion, + ) - return nil + return nil + */ } diff --git a/Client/Package/InstallPackage.go b/Client/Package/InstallPackage.go index f514594..24c4fda 100644 --- a/Client/Package/InstallPackage.go +++ b/Client/Package/InstallPackage.go @@ -27,7 +27,7 @@ func InstallPackage(pkgs []string) error { "Installing %s...\n", pkg, ) - e = Archive.UntarGzip(pkg, Variables.DestDir) + e = Archive.UntarGzip(pkg, Variables.RootDir) fmt.Printf( "%s successfully installed\n", pkg, diff --git a/Client/main.go b/Client/main.go index b875ccc..967d4fb 100644 --- a/Client/main.go +++ b/Client/main.go @@ -6,19 +6,21 @@ import ( "PackageManager/Client/Database" "PackageManager/Client/Filesystem" - "PackageManager/Client/Package" "PackageManager/Color" "PackageManager/Helper" + "PackageManager/Variables" ) func main() { var ( - updateFilesytemFlag bool - updateFilesytemFlagLong bool - createPackageFlag bool - createPackageFlagLong bool - installLocalPackageFlag bool - installLocalPackageFlagLong bool + getFilesystemDiffFlag bool + getFilesystemDiffFlagLong bool + addFileDiffFlag bool + addFileDiffFlagLong bool + commitAddedFilesFlag bool + commitAddedFilesFlagLong bool + resetAddedFilesFlag bool + resetAddedFilesFlagLong bool e error ) @@ -34,20 +36,38 @@ func main() { panic(e) } + // TODO: Rework usage function + // Initialise flags - flag.BoolVar(&updateFilesytemFlag, "Uf", false, "Update filesystem database") - flag.BoolVar(&updateFilesytemFlagLong, "-update-filesystem", false, "Update filesystem database") - flag.BoolVar(&createPackageFlag, "Cp", false, "Create package") - flag.BoolVar(&createPackageFlagLong, "-create-package", false, "Create Package") + flag.BoolVar(&getFilesystemDiffFlag, "Fd", false, "Filesystem diff") + flag.BoolVar(&getFilesystemDiffFlagLong, "fs-diff", false, "Filesystem diff") + + flag.BoolVar(&addFileDiffFlag, "Af", false, "Add files") + flag.BoolVar(&addFileDiffFlagLong, "add-files", false, "Add files") + + flag.BoolVar(&commitAddedFilesFlag, "Cf", false, "Add files") + flag.BoolVar(&commitAddedFilesFlagLong, "commit", false, "Add files") - flag.BoolVar(&installLocalPackageFlag, "Il", false, "Install local package") - flag.BoolVar(&installLocalPackageFlagLong, "-install-local-package", false, "Install local Package") + flag.BoolVar(&resetAddedFilesFlag, "Rf", false, "Reset added files") + flag.BoolVar(&resetAddedFilesFlagLong, "reset", false, "Reset added files") flag.Parse() - if updateFilesytemFlag || updateFilesytemFlagLong { - e = Filesystem.UpdateFilesystemHash() + if getFilesystemDiffFlag || getFilesystemDiffFlagLong { + var rootPath string = Variables.RootDir + if len(flag.Args()) > 1 { + // TODO: Fix this msg + fmt.Println(Color.Fatal("Option takes one optional argument")) + flag.Usage() + return + } + + if len(flag.Args()) == 1 { + rootPath = flag.Arg(0) + } + + e = Filesystem.ShowFilesystemDiff(rootPath) if e != nil { panic(e) } @@ -55,22 +75,53 @@ func main() { return } - if createPackageFlag || createPackageFlagLong { - e = Package.CreatePackage() + if addFileDiffFlag || addFileDiffFlagLong { + if len(flag.Args()) > 1 && len(flag.Args()) < 1 { + fmt.Println(Color.Fatal("Must supply one argument")) + flag.Usage() + return + } + e = Filesystem.PickFiles(flag.Arg(0)) + if e != nil { + panic(e) + } + return + } + + if commitAddedFilesFlag || commitAddedFilesFlagLong { + e = Filesystem.CommitFiles() if e != nil { panic(e) } return } - if installLocalPackageFlag || installLocalPackageFlagLong { - e = Package.InstallPackage(flag.Args()) + if resetAddedFilesFlag || resetAddedFilesFlagLong { + e = Filesystem.ResetAllPickedFiles() if e != nil { panic(e) } return } + /* + if createPackageFlag || createPackageFlagLong { + e = Package.CreatePackage() + if e != nil { + panic(e) + } + return + } + + if installLocalPackageFlag || installLocalPackageFlagLong { + e = Package.InstallPackage(flag.Args()) + if e != nil { + panic(e) + } + return + } + */ + flag.Usage() fmt.Println(Color.Fatal("Nothing to do")) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1d594c0 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +CLIENT_MAIN=Client/main.go + +BUILD=go build -o +BUILD32=env GOARCH=386 go build + +LINUX_LDFLAGS=--ldflags "-s -w -extldflags=-static" + +LINUX_ENV=env GOOS=linux GOARCH=amd64 +LINUX_ENV32=env GOOS=linux GOARCH=386 + +LINUX_OUT=tjpkg + +build: + ${LINUX_ENV} ${BUILD} ${LINUX_OUT} ${CLIENT_MAIN} diff --git a/Variables/Variables.go b/Variables/Variables.go index f0959cf..fd12a60 100644 --- a/Variables/Variables.go +++ b/Variables/Variables.go @@ -5,20 +5,45 @@ import ( ) const ( - DatabaseName string = "package_manager.db" + DatabaseName string = "package_manager.db" + FsHashDatabaseName string = "fs_hash.db" ) var ( - DestDir string = "/" - InstallDirs []string = []string{"/bin", "/etc", "/lib", "/lib64", "/sbin", "/usr"} + RootDir string = "/" + FsHashPicksBucket []byte = []byte("FilesystemPicks") + FsHashIndexBucket []byte = []byte("FilesystemIndex") + + PruneRegexPaths []string = []string{ + "^/\\.git$", + "^/dist$", + "^/boot/grub$", + "^/proc$", + "^/dev$", + "^/mnt$", + "^/sys$", + "^/src$", + "^/root$", + "^/home$", + "^/build$", + "^/tools$", + "/lost\\+found$", + } + + IgnoreRegexPaths []string = []string{ + "^/etc/passwd$", + "^/etc/passwd-$", + "^/etc/group$", + "^/etc/group-$", + } ) func init() { var ( - destDir string + rootDir string ) - destDir = os.Getenv("DESTDIR") - if destDir != "" { - DestDir = destDir + rootDir = os.Getenv("ROOTDIR") + if rootDir != "" { + RootDir = rootDir } }