timetable-extension #1
1
go.mod
1
go.mod
@ -23,4 +23,5 @@ require (
|
|||||||
golang.org/x/crypto v0.24.0 // indirect
|
golang.org/x/crypto v0.24.0 // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
golang.org/x/text v0.16.0 // indirect
|
golang.org/x/text v0.16.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
1
go.sum
1
go.sum
@ -96,6 +96,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
|||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
29
pis/data.go
Normal file
29
pis/data.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package pis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Process the YAML data to a struct
|
||||||
|
func processYaml(yamlStr string) (*PisData, error) {
|
||||||
|
var pis PisData
|
||||||
|
|
||||||
|
err := yaml.Unmarshal([]byte(yamlStr), &pis)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to unmarshal YAML: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = deduplicateCodes(&pis)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pis, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deduplicate data in place and return error if failed
|
||||||
|
func deduplicateCodes(pis *PisData) error {
|
||||||
|
return fmt.Errorf("deduplication logic not present, unable to update")
|
||||||
|
}
|
@ -7,3 +7,9 @@ type GiteaReleaseData struct {
|
|||||||
Draft bool `json:"draft"`
|
Draft bool `json:"draft"`
|
||||||
Prerelease bool `json:"prerelease"`
|
Prerelease bool `json:"prerelease"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PisData struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
Stops []string `json:"stops"`
|
||||||
|
Operator string `json:"operator"`
|
||||||
|
}
|
||||||
|
161
pis/update.go
161
pis/update.go
@ -1,11 +1,166 @@
|
|||||||
package pis
|
package pis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"compress/gzip"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
destPath = "/tmp/pis.tar.gz"
|
||||||
|
extractPath = "/tmp/extract"
|
||||||
|
)
|
||||||
|
|
||||||
// Downloads the release tarball, extracts then applies to database
|
// Downloads the release tarball, extracts then applies to database
|
||||||
func runUpdate(tarballUrl string) error {
|
func runUpdate(tarballUrl string) error {
|
||||||
// Download and extract tarball
|
err := downloadFile(tarballUrl, destPath)
|
||||||
// load PIS yaml files
|
if err != nil {
|
||||||
// Run code deduplication
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract to disk
|
||||||
|
file, err := os.Open(destPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error opening file: %v\n", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
if err := extractFiles(file, extractPath); err != nil {
|
||||||
|
fmt.Printf("Error extracting file: %v\n", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load YAML to string
|
||||||
|
pisData, err := extractYamlData(extractPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Replace database collection with new data
|
// Replace database collection with new data
|
||||||
// Ensure indeces are present
|
// Ensure indeces are present
|
||||||
|
|
||||||
|
// Cleanup files
|
||||||
|
cleanupFiles(destPath, extractPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Download the tarball to disk
|
||||||
|
func downloadFile(url, filepath string) error {
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
out, err := os.Create(filepath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(out, resp.Body)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract tarball to disk
|
||||||
|
func extractFiles(gzipStream io.Reader, dest string) error {
|
||||||
|
uncompressedStream, err := gzip.NewReader(gzipStream)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer uncompressedStream.Close()
|
||||||
|
|
||||||
|
tarReader := tar.NewReader(uncompressedStream)
|
||||||
|
|
||||||
|
for {
|
||||||
|
header, err := tarReader.Next()
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
filePath := filepath.Join(dest, header.Name)
|
||||||
|
|
||||||
|
switch header.Typeflag {
|
||||||
|
case tar.TypeDir:
|
||||||
|
if err := os.MkdirAll(filepath.Join(dest, header.Name), 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case tar.TypeReg:
|
||||||
|
outFile, err := os.Create(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.Copy(outFile, tarReader); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outFile.Close()
|
||||||
|
default:
|
||||||
|
fmt.Printf("Unable to handle filetype %c in %s\n", header.Typeflag, header.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return YAML PIS files as a string
|
||||||
|
func extractYamlData(dir string) (string, error) {
|
||||||
|
var allContent strings.Builder // Using a string builder to accumulate content
|
||||||
|
|
||||||
|
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err // Only returning error since Walk callback doesn't accept string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the path contains 'pis' and has a .yaml or .yml extension
|
||||||
|
if strings.Contains(path, "/pis/") && !info.IsDir() &&
|
||||||
|
(strings.HasSuffix(info.Name(), ".yaml") || strings.HasSuffix(info.Name(), ".yml")) {
|
||||||
|
fmt.Printf("Processing YAML file in 'pis' directory: %s\n", path)
|
||||||
|
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open YAML file %s: %v", path, err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
content, err := io.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read YAML file %s: %v", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulate content from each YAML file in 'pis' directory
|
||||||
|
allContent.Write(content)
|
||||||
|
allContent.WriteString("\n") // Add a newline between file contents
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the accumulated content as a single string
|
||||||
|
return allContent.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleans up downloaded and extracted files
|
||||||
|
func cleanupFiles(paths ...string) {
|
||||||
|
for _, path := range paths {
|
||||||
|
err := os.RemoveAll(path)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error removing %s: %v\n", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user