gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package unittest
  4. import (
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "code.gitea.io/gitea/modules/util"
  9. )
  10. // SyncFile synchronizes the two files. This is skipped if both files
  11. // exist and the size, modtime, and mode match.
  12. func SyncFile(srcPath, destPath string) error {
  13. dest, err := os.Stat(destPath)
  14. if err != nil {
  15. if os.IsNotExist(err) {
  16. return util.CopyFile(srcPath, destPath)
  17. }
  18. return err
  19. }
  20. src, err := os.Stat(srcPath)
  21. if err != nil {
  22. return err
  23. }
  24. if src.Size() == dest.Size() &&
  25. src.ModTime().Equal(dest.ModTime()) &&
  26. src.Mode() == dest.Mode() {
  27. return nil
  28. }
  29. return util.CopyFile(srcPath, destPath)
  30. }
  31. // SyncDirs synchronizes files recursively from source to target directory.
  32. // It returns error when error occurs in underlying functions.
  33. func SyncDirs(srcPath, destPath string) error {
  34. err := os.MkdirAll(destPath, os.ModePerm)
  35. if err != nil {
  36. return err
  37. }
  38. // the keep file is used to keep the directory in a git repository, it doesn't need to be synced
  39. // and go-git doesn't work with the ".keep" file (it would report errors like "ref is empty")
  40. const keepFile = ".keep"
  41. // find and delete all untracked files
  42. destFiles, err := util.ListDirRecursively(destPath, &util.ListDirOptions{IncludeDir: true})
  43. if err != nil {
  44. return err
  45. }
  46. for _, destFile := range destFiles {
  47. destFilePath := filepath.Join(destPath, destFile)
  48. shouldRemove := filepath.Base(destFilePath) == keepFile
  49. if _, err = os.Stat(filepath.Join(srcPath, destFile)); err != nil {
  50. if os.IsNotExist(err) {
  51. shouldRemove = true
  52. } else {
  53. return err
  54. }
  55. }
  56. // if src file does not exist, remove dest file
  57. if shouldRemove {
  58. if err = os.RemoveAll(destFilePath); err != nil {
  59. return err
  60. }
  61. }
  62. }
  63. // sync src files to dest
  64. srcFiles, err := util.ListDirRecursively(srcPath, &util.ListDirOptions{IncludeDir: true})
  65. if err != nil {
  66. return err
  67. }
  68. for _, srcFile := range srcFiles {
  69. destFilePath := filepath.Join(destPath, srcFile)
  70. // util.ListDirRecursively appends a slash to the directory name
  71. if strings.HasSuffix(srcFile, "/") {
  72. err = os.MkdirAll(destFilePath, os.ModePerm)
  73. } else if filepath.Base(destFilePath) != keepFile {
  74. err = SyncFile(filepath.Join(srcPath, srcFile), destFilePath)
  75. }
  76. if err != nil {
  77. return err
  78. }
  79. }
  80. return nil
  81. }