import.go 2.9 KB

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