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.

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