import.go 2.9 KB

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