import.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Copyright 2016 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package cmd
  5. import (
  6. "bufio"
  7. "bytes"
  8. "fmt"
  9. "os"
  10. "path/filepath"
  11. "time"
  12. "github.com/pkg/errors"
  13. "github.com/unknwon/com"
  14. "github.com/urfave/cli"
  15. "gogs.io/gogs/internal/conf"
  16. )
  17. var (
  18. Import = cli.Command{
  19. Name: "import",
  20. Usage: "Import portable data as local Gogs data",
  21. Description: `Allow user import data from other Gogs installations to local instance
  22. without manually hacking the data files`,
  23. Subcommands: []cli.Command{
  24. subcmdImportLocale,
  25. },
  26. }
  27. subcmdImportLocale = cli.Command{
  28. Name: "locale",
  29. Usage: "Import locale files to local repository",
  30. Action: runImportLocale,
  31. Flags: []cli.Flag{
  32. stringFlag("source", "", "Source directory that stores new locale files"),
  33. stringFlag("target", "", "Target directory that stores old locale files"),
  34. stringFlag("config, c", "", "Custom configuration file path"),
  35. },
  36. }
  37. )
  38. func runImportLocale(c *cli.Context) error {
  39. if !c.IsSet("source") {
  40. return errors.New("source directory is not specified")
  41. } else if !c.IsSet("target") {
  42. return errors.New("target directory is not specified")
  43. }
  44. if !com.IsDir(c.String("source")) {
  45. return fmt.Errorf("source directory %q does not exist or is not a directory", c.String("source"))
  46. } else if !com.IsDir(c.String("target")) {
  47. return fmt.Errorf("target directory %q does not exist or is not a directory", c.String("target"))
  48. }
  49. err := conf.Init(c.String("config"))
  50. if err != nil {
  51. return errors.Wrap(err, "init configuration")
  52. }
  53. now := time.Now()
  54. var line []byte
  55. badChars := []byte(`="`)
  56. escapedQuotes := []byte(`\"`)
  57. regularQuotes := []byte(`"`)
  58. // Cut out en-US.
  59. for _, lang := range conf.I18n.Langs[1:] {
  60. name := fmt.Sprintf("locale_%s.ini", lang)
  61. source := filepath.Join(c.String("source"), name)
  62. target := filepath.Join(c.String("target"), name)
  63. if !com.IsFile(source) {
  64. continue
  65. }
  66. // Crowdin surrounds double quotes for strings contain quotes inside,
  67. // this breaks INI parser, we need to fix that.
  68. sr, err := os.Open(source)
  69. if err != nil {
  70. return fmt.Errorf("Open: %v", err)
  71. }
  72. tw, err := os.Create(target)
  73. if err != nil {
  74. if err != nil {
  75. return fmt.Errorf("Open: %v", err)
  76. }
  77. }
  78. scanner := bufio.NewScanner(sr)
  79. for scanner.Scan() {
  80. line = scanner.Bytes()
  81. idx := bytes.Index(line, badChars)
  82. if idx > -1 && line[len(line)-1] == '"' {
  83. // We still want the "=" sign
  84. line = append(line[:idx+1], line[idx+2:len(line)-1]...)
  85. line = bytes.ReplaceAll(line, escapedQuotes, regularQuotes)
  86. }
  87. _, _ = tw.Write(line)
  88. _, _ = tw.WriteString("\n")
  89. }
  90. _ = sr.Close()
  91. _ = tw.Close()
  92. // Modification time of files from Crowdin often ahead of current,
  93. // so we need to set back to current.
  94. _ = os.Chtimes(target, now, now)
  95. }
  96. fmt.Println("Locale files has been successfully imported!")
  97. return nil
  98. }