main.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package main
  2. import (
  3. "encoding/csv"
  4. "fmt"
  5. "html/template"
  6. "io"
  7. "os"
  8. )
  9. const apacheTemplate = `
  10. {{/* Do not edit: generated by tsv2htaccess*/}}
  11. {{ range . }}
  12. {{- /*gotype: code.osinet.fr/fgm/go_tooling/tsv2htaccess.redirect*/ -}}
  13. RewriteRule ^{{ .Clean }}$ {{ .Target }} [L,NC,NE,R=301]
  14. {{ end }}
  15. `
  16. type redirect struct {
  17. Clean, Target string
  18. }
  19. func main() {
  20. var err error
  21. if len(os.Args) != 4 {
  22. fmt.Fprintf(os.Stderr, `
  23. Syntax:
  24. %s source destination prefix
  25. Where:
  26. - source URL pairs in TSV format
  27. - destination Apache .htaccess fragment
  28. - prefix Prefix to strip from source URLs in pairs
  29. `, os.Args[0])
  30. return
  31. }
  32. source := os.Args[1]
  33. dest := os.Args[2]
  34. prefix := os.Args[3]
  35. fmt.Fprintf(os.Stderr, "Converting %s to %s, stripping %s\n", source, dest, prefix)
  36. var tsv io.ReadCloser
  37. tsv, err = os.Open(source)
  38. if err != nil {
  39. panic(err)
  40. }
  41. defer tsv.Close()
  42. redirects, err := read(tsv, prefix)
  43. if err != nil {
  44. panic(err)
  45. }
  46. hta, err := os.Create(dest)
  47. if err != nil {
  48. panic(err)
  49. }
  50. defer hta.Close()
  51. write(hta, redirects)
  52. }
  53. func read(tsv io.Reader, expectedPrefix string) ([]redirect, error) {
  54. var err error
  55. l := len(expectedPrefix)
  56. r := csv.NewReader(tsv)
  57. r.Comma = '\t'
  58. r.FieldsPerRecord = 2
  59. rows, err := r.ReadAll()
  60. if err != nil {
  61. return nil, err
  62. }
  63. redirects := make([]redirect, len(rows))
  64. for i, rawRow := range rows {
  65. absClean := rawRow[0]
  66. actualPrefix := absClean[0:l]
  67. if actualPrefix != expectedPrefix {
  68. panic(fmt.Errorf("incorrect source prefix: [%s], should be [%s]", actualPrefix, expectedPrefix))
  69. }
  70. clean := absClean[l:]
  71. redirects[i] = redirect{Clean: clean, Target: rawRow[1]}
  72. }
  73. return redirects, nil
  74. }
  75. func write(w io.Writer, redirects []redirect) {
  76. tpl := template.Must(template.New("htaccess").Parse(apacheTemplate))
  77. err := tpl.Execute(w, redirects)
  78. if err != nil {
  79. panic(err)
  80. }
  81. tpl.Execute(os.Stderr, redirects)
  82. }