PackageManager just because
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
4.1 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package Filesystem
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "runtime"
  8. "github.com/vbauerster/mpb"
  9. bolt "go.etcd.io/bbolt"
  10. "golang.org/x/sync/semaphore"
  11. "PackageManager/Client/Database"
  12. "PackageManager/Client/ProgressBar"
  13. "PackageManager/Color"
  14. "PackageManager/Variables"
  15. )
  16. type FilesystemStatus struct {
  17. NewFiles []string
  18. PickedFiles []string
  19. ModifiedFiles []string
  20. MissingFiles []string
  21. }
  22. func ShowFilesystemDiff(root string) error {
  23. var (
  24. fsStatus FilesystemStatus
  25. //f string
  26. e error
  27. )
  28. fsStatus, e = GetFilesystemDiff(root)
  29. if e != nil {
  30. return e
  31. }
  32. fmt.Println("New files:")
  33. PrintFilesOrLength(fsStatus.NewFiles, Color.Green)
  34. fmt.Println("Added files:")
  35. PrintFilesOrLength(fsStatus.PickedFiles, Color.Green)
  36. fmt.Println("Modified files:")
  37. PrintFilesOrLength(fsStatus.ModifiedFiles, Color.Warning)
  38. fmt.Println("Deleted files:")
  39. PrintFilesOrLength(fsStatus.MissingFiles, Color.Fatal)
  40. return nil
  41. }
  42. func GetFilesystemLength(root string) (int, error) {
  43. var (
  44. rootStat os.FileInfo
  45. fsCount int = 0
  46. e error
  47. )
  48. rootStat, e = os.Stat(root)
  49. if e != nil {
  50. return fsCount, e
  51. }
  52. if rootStat.IsDir() && root[len(root)-1:] != "/" {
  53. root = root + "/"
  54. }
  55. filepath.Walk(root, func(p string, i os.FileInfo, _ error) error {
  56. // Ignore path in Variables.PruneRegexPaths
  57. if i.IsDir() && matchAny(p, PruneRegex) {
  58. return filepath.SkipDir
  59. }
  60. // Ignore path in Variables.IgnoreRegexPaths
  61. if matchAny(p, IgnoreRegex) {
  62. return nil
  63. }
  64. if !i.Mode().IsRegular() && (i.Mode()&os.ModeSymlink == 0) {
  65. return nil
  66. }
  67. fsCount++
  68. return nil
  69. })
  70. return fsCount, e
  71. }
  72. func (fsStatus *FilesystemStatus) parseFile(indexBucket, picksBucket *bolt.Bucket, p string, bar *mpb.Bar) {
  73. var (
  74. newFileObject FileObject
  75. knownFileObject FileObject
  76. pick, known []byte
  77. e error
  78. )
  79. defer func() {
  80. bar.Increment()
  81. }()
  82. pick = picksBucket.Get([]byte(p))
  83. known = indexBucket.Get([]byte(p))
  84. if pick != nil {
  85. fsStatus.PickedFiles = append(fsStatus.PickedFiles, p)
  86. return
  87. }
  88. if known != nil {
  89. newFileObject, e = CreateFileObject(p)
  90. if e != nil {
  91. return
  92. }
  93. knownFileObject, e = FromBytes(known)
  94. if e != nil {
  95. return
  96. }
  97. e = newFileObject.IsDifferent(knownFileObject)
  98. if e != nil {
  99. fsStatus.ModifiedFiles = append(fsStatus.ModifiedFiles, p)
  100. }
  101. return
  102. }
  103. fsStatus.NewFiles = append(fsStatus.NewFiles, p)
  104. return
  105. }
  106. func GetFilesystemDiff(root string) (FilesystemStatus, error) {
  107. var (
  108. fsStatus FilesystemStatus = FilesystemStatus{}
  109. sem *semaphore.Weighted
  110. picksBucket *bolt.Bucket
  111. indexBucket *bolt.Bucket
  112. rootStat os.FileInfo
  113. bar *mpb.Bar
  114. fsCount int
  115. poolSize int
  116. e error
  117. )
  118. poolSize = runtime.NumCPU()
  119. sem = semaphore.NewWeighted(int64(poolSize))
  120. rootStat, e = os.Stat(root)
  121. if e != nil {
  122. return fsStatus, e
  123. }
  124. if rootStat.IsDir() && root[len(root)-1:] != "/" {
  125. root = root + "/"
  126. }
  127. fsCount, e = GetFilesystemLength(root)
  128. if e != nil {
  129. return fsStatus, e
  130. }
  131. bar = ProgressBar.InitBar("Scanning...", fsCount)
  132. e = Database.FsDB.View(func(tx *bolt.Tx) error {
  133. picksBucket = tx.Bucket(Variables.FsHashPicksBucket)
  134. indexBucket = tx.Bucket(Variables.FsHashIndexBucket)
  135. filepath.Walk(root, func(p string, i os.FileInfo, _ error) error {
  136. // Ignore path in Variables.PruneRegexPaths
  137. if i.IsDir() && matchAny(p, PruneRegex) {
  138. return filepath.SkipDir
  139. }
  140. // Ignore path in Variables.IgnoreRegexPaths
  141. if matchAny(p, IgnoreRegex) {
  142. return nil
  143. }
  144. if !i.Mode().IsRegular() && (i.Mode()&os.ModeSymlink == 0) {
  145. return nil
  146. }
  147. Variables.WG.Add(1)
  148. sem.Acquire(context.Background(), 1)
  149. go func() {
  150. fsStatus.parseFile(indexBucket, picksBucket, p, bar)
  151. Variables.WG.Done()
  152. sem.Release(1)
  153. }()
  154. return nil
  155. })
  156. indexBucket.ForEach(func(k, v []byte) error {
  157. _, e = os.Lstat(string(k))
  158. if os.IsNotExist(e) {
  159. fsStatus.MissingFiles = append(fsStatus.MissingFiles, string(k))
  160. }
  161. return nil
  162. })
  163. Variables.WG.Wait()
  164. ProgressBar.CloseBar(bar)
  165. return nil
  166. })
  167. return fsStatus, e
  168. }