package Filesystem import ( "PackageManager/Client/Database" "PackageManager/Color" "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 } fmt.Println("New files:") PrintFilesOrLength(fsStatus.NewFiles, Color.Green) fmt.Println("Added files:") PrintFilesOrLength(fsStatus.PickedFiles, Color.Green) fmt.Println("Modified files:") PrintFilesOrLength(fsStatus.ModifiedFiles, Color.Warning) fmt.Println("Deleted files:") PrintFilesOrLength(fsStatus.MissingFiles, Color.Fatal) return nil } func GetFilesystemLength(root string) (int, error) { var ( rootStat os.FileInfo fsCount int = 0 e error ) rootStat, e = os.Stat(root) if e != nil { return fsCount, e } if rootStat.IsDir() && root[len(root)-1:] != "/" { root = root + "/" } 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 } fsCount++ return nil }) return fsCount, e } 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.FsHashIndexBucket) 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 }