import.go 3.0 KB

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