|
@@ -1,26 +1,12 @@
|
|
|
package file
|
|
|
|
|
|
import (
|
|
|
- "bufio"
|
|
|
- "bytes"
|
|
|
- "encoding/json"
|
|
|
"errors"
|
|
|
- "fmt"
|
|
|
- "io"
|
|
|
- "io/fs"
|
|
|
- "io/ioutil"
|
|
|
- "os"
|
|
|
- "path"
|
|
|
"path/filepath"
|
|
|
- "strings"
|
|
|
"sync"
|
|
|
- "time"
|
|
|
|
|
|
- "git.andreafazzi.eu/andrea/probo/client"
|
|
|
"git.andreafazzi.eu/andrea/probo/hasher/sha256"
|
|
|
- "git.andreafazzi.eu/andrea/probo/models"
|
|
|
"git.andreafazzi.eu/andrea/probo/store/memory"
|
|
|
- "github.com/go-yaml/yaml"
|
|
|
)
|
|
|
|
|
|
var (
|
|
@@ -61,109 +47,6 @@ func NewFileProboCollectorStore(dirname string) (*FileProboCollectorStore, error
|
|
|
return s, nil
|
|
|
}
|
|
|
|
|
|
-func (s *FileProboCollectorStore) GetQuizzesDir() string {
|
|
|
- return s.quizzesDir
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) GetCollectionsDir() string {
|
|
|
- return s.collectionsDir
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) reindexQuizzes() error {
|
|
|
- files, err := ioutil.ReadDir(s.quizzesDir)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- markdownFiles := make([]fs.FileInfo, 0)
|
|
|
-
|
|
|
- for _, file := range files {
|
|
|
- filename := file.Name()
|
|
|
- if !file.IsDir() && strings.HasSuffix(filename, ".md") {
|
|
|
- markdownFiles = append(markdownFiles, file)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if len(markdownFiles) == 0 {
|
|
|
- return fmt.Errorf("The directory is empty.")
|
|
|
- }
|
|
|
-
|
|
|
- for _, file := range markdownFiles {
|
|
|
- filename := file.Name()
|
|
|
- fullPath := filepath.Join(s.quizzesDir, filename)
|
|
|
-
|
|
|
- content, err := os.ReadFile(fullPath)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- quiz, meta, err := QuizFromMarkdown(string(content))
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- q, err := s.memoryStore.CreateQuiz(&client.CreateUpdateQuizRequest{
|
|
|
- Quiz: quiz,
|
|
|
- Meta: meta,
|
|
|
- })
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- if meta == nil {
|
|
|
- s.WriteMetaHeaderToFile(filename, &models.Meta{
|
|
|
- ID: q.ID,
|
|
|
- CreatedAt: time.Now(),
|
|
|
- })
|
|
|
- }
|
|
|
- s.SetQuizPath(q, fullPath)
|
|
|
- }
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) reindexCollections() error {
|
|
|
- files, err := ioutil.ReadDir(s.collectionsDir)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- jsonFiles := make([]fs.FileInfo, 0)
|
|
|
-
|
|
|
- for _, file := range files {
|
|
|
- filename := file.Name()
|
|
|
- if !file.IsDir() && strings.HasSuffix(filename, ".json") {
|
|
|
- jsonFiles = append(jsonFiles, file)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for _, file := range jsonFiles {
|
|
|
- filename := file.Name()
|
|
|
- fullPath := filepath.Join(s.collectionsDir, filename)
|
|
|
-
|
|
|
- content, err := os.ReadFile(fullPath)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- var clientCollection *client.Collection
|
|
|
-
|
|
|
- err = json.Unmarshal(content, &clientCollection)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- collection, err := s.memoryStore.CreateCollection(&client.CreateUpdateCollectionRequest{
|
|
|
- Collection: clientCollection,
|
|
|
- })
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- s.SetCollectionPath(collection, fullPath)
|
|
|
- }
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
func (s *FileProboCollectorStore) Reindex() error {
|
|
|
s.memoryStore = memory.NewMemoryProboCollectorStore(
|
|
|
sha256.NewDefault256Hasher(sha256.DefaultSHA256HashingFn),
|
|
@@ -184,501 +67,3 @@ func (s *FileProboCollectorStore) Reindex() error {
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) ReadAllQuizzes() ([]*models.Quiz, error) {
|
|
|
- return s.memoryStore.ReadAllQuizzes()
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) CreateQuiz(r *client.CreateUpdateQuizRequest) (*models.Quiz, error) {
|
|
|
- quiz, err := s.memoryStore.CreateQuiz(r)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- err = s.createOrUpdateMarkdownFile(quiz)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- err = s.Reindex()
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- return s.memoryStore.ReadQuizByHash(quiz.Hash)
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) UpdateQuiz(r *client.CreateUpdateQuizRequest, id string) (*models.Quiz, error) {
|
|
|
- quiz, updated, err := s.memoryStore.UpdateQuiz(r, id)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- if updated { // Update and re-index only if quiz hash is changed
|
|
|
- err = s.createOrUpdateMarkdownFile(quiz)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- err = s.Reindex()
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- }
|
|
|
- return s.memoryStore.ReadQuizByHash(quiz.Hash)
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) DeleteQuiz(r *client.DeleteQuizRequest) (*models.Quiz, error) {
|
|
|
- quiz, err := s.memoryStore.DeleteQuiz(r.ID)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- path, err := s.GetQuizPath(quiz)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- err = os.Remove(path)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- err = s.Reindex()
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- return quiz, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) GetQuizPath(quiz *models.Quiz) (string, error) {
|
|
|
- if quiz == nil {
|
|
|
- return "", errors.New("Quiz object passed as argument is nil!")
|
|
|
- }
|
|
|
-
|
|
|
- s.lock.RLock()
|
|
|
- defer s.lock.RUnlock()
|
|
|
-
|
|
|
- path, ok := s.quizzesPaths[quiz.ID]
|
|
|
- if !ok {
|
|
|
- return "", errors.New(fmt.Sprintf("Path not found for quiz ID %v", quiz.ID))
|
|
|
- }
|
|
|
- return path, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) GetCollectionPath(collection *models.Collection) (string, error) {
|
|
|
- s.lock.RLock()
|
|
|
- defer s.lock.RUnlock()
|
|
|
-
|
|
|
- path, ok := s.collectionsPaths[collection.ID]
|
|
|
- if !ok {
|
|
|
- return "", errors.New(fmt.Sprintf("Path not found for collection ID %v", collection.ID))
|
|
|
- }
|
|
|
- return path, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) SetQuizPath(quiz *models.Quiz, path string) string {
|
|
|
- s.lock.Lock()
|
|
|
- defer s.lock.Unlock()
|
|
|
-
|
|
|
- s.quizzesPaths[quiz.ID] = path
|
|
|
-
|
|
|
- return path
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) SetCollectionPath(collection *models.Collection, path string) string {
|
|
|
- s.lock.Lock()
|
|
|
- defer s.lock.Unlock()
|
|
|
-
|
|
|
- s.collectionsPaths[collection.ID] = path
|
|
|
-
|
|
|
- return path
|
|
|
-}
|
|
|
-
|
|
|
-func MarkdownFromQuiz(quiz *models.Quiz) (string, error) {
|
|
|
- if quiz.Question == nil {
|
|
|
- return "", errors.New("Quiz should contain a question but it wasn't provided.")
|
|
|
- }
|
|
|
-
|
|
|
- if len(quiz.Answers) < 2 {
|
|
|
- return "", errors.New("Quiz should contain at least 2 answers but none was provided.")
|
|
|
- }
|
|
|
-
|
|
|
- if quiz.Correct == nil {
|
|
|
- return "", errors.New("Quiz should contain a correct answer but not was provided.")
|
|
|
- }
|
|
|
-
|
|
|
- correctAnswer := "* " + quiz.Correct.Text
|
|
|
- var otherAnswers string
|
|
|
-
|
|
|
- for _, answer := range quiz.Answers {
|
|
|
- if quiz.Correct.ID != answer.ID {
|
|
|
- otherAnswers += "* " + answer.Text + "\n"
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- markdown := quiz.Question.Text + "\n\n" + correctAnswer + "\n" + otherAnswers
|
|
|
-
|
|
|
- return markdown, nil
|
|
|
-}
|
|
|
-
|
|
|
-func QuizFromMarkdown(markdown string) (*client.Quiz, *models.Meta, error) {
|
|
|
- meta, remainingMarkdown, err := parseMetaHeaderFromMarkdown(markdown)
|
|
|
- if err != nil {
|
|
|
- return nil, nil, err
|
|
|
- }
|
|
|
-
|
|
|
- lines := strings.Split(remainingMarkdown, "\n")
|
|
|
-
|
|
|
- questionText := ""
|
|
|
- answers := []*client.Answer{}
|
|
|
-
|
|
|
- for _, line := range lines {
|
|
|
- if strings.HasPrefix(line, "*") {
|
|
|
- answerText := strings.TrimPrefix(line, "* ")
|
|
|
- correct := len(answers) == 0
|
|
|
- answer := &client.Answer{Text: answerText, Correct: correct}
|
|
|
- answers = append(answers, answer)
|
|
|
- } else {
|
|
|
- if questionText != "" {
|
|
|
- questionText += "\n"
|
|
|
- }
|
|
|
- questionText += line
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- questionText = strings.TrimRight(questionText, "\n")
|
|
|
-
|
|
|
- if questionText == "" {
|
|
|
- return nil, nil, fmt.Errorf("Question text should not be empty.")
|
|
|
- }
|
|
|
-
|
|
|
- if len(answers) < 2 {
|
|
|
- return nil, nil, fmt.Errorf("Number of answers should be at least 2 but parsed answers are %d.", len(answers))
|
|
|
- }
|
|
|
-
|
|
|
- question := &client.Question{Text: questionText}
|
|
|
- quiz := &client.Quiz{Question: question, Answers: answers}
|
|
|
-
|
|
|
- return quiz, meta, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) ReadMetaHeaderFromFile(filename string) (*models.Meta, error) {
|
|
|
- data, err := ioutil.ReadFile(path.Join(s.quizzesDir, filename))
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- meta, _, err := parseMetaHeaderFromMarkdown(string(data))
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return meta, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) WriteMetaHeaderToFile(filename string, meta *models.Meta) (*models.Meta, error) {
|
|
|
- readMeta, err := s.ReadMetaHeaderFromFile(filename)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- if readMeta == nil {
|
|
|
- _, err := writeMetaHeader(path.Join(s.quizzesDir, filename), meta)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return meta, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) ReadAllCollections() ([]*models.Collection, error) {
|
|
|
- return s.memoryStore.ReadAllCollections()
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) CreateCollection(r *client.CreateUpdateCollectionRequest) (*models.Collection, error) {
|
|
|
- collection, err := s.memoryStore.CreateCollection(r)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- err = s.createOrUpdateCollectionFile(collection)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- return s.memoryStore.ReadCollectionByID(collection.ID)
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) UpdateCollection(r *client.CreateUpdateCollectionRequest, id string) (*models.Collection, error) {
|
|
|
- collection, _, err := s.memoryStore.UpdateCollection(r, id)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- err = s.createOrUpdateCollectionFile(collection)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- return s.memoryStore.ReadCollectionByID(collection.ID)
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) removeMetaFromFile(filename string) (*models.Meta, error) {
|
|
|
- file, err := os.Open(path.Join(s.quizzesDir, filename))
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- defer file.Close()
|
|
|
-
|
|
|
- var buffer bytes.Buffer
|
|
|
-
|
|
|
- reader := bufio.NewReader(file)
|
|
|
-
|
|
|
- var meta models.Meta
|
|
|
- var line string
|
|
|
- var sb strings.Builder
|
|
|
- for {
|
|
|
- line, err = reader.ReadString('\n')
|
|
|
- if err != nil {
|
|
|
- if err == io.EOF {
|
|
|
- break
|
|
|
- }
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- if strings.TrimSpace(line) == "---" {
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for {
|
|
|
- line, err = reader.ReadString('\n')
|
|
|
- if err != nil {
|
|
|
- if err == io.EOF {
|
|
|
- break
|
|
|
- }
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- if strings.TrimSpace(line) == "---" {
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- sb.WriteString(line)
|
|
|
- }
|
|
|
-
|
|
|
- err = yaml.Unmarshal([]byte(sb.String()), &meta)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- _, err = io.Copy(&buffer, reader)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- file, err = os.Create(path.Join(s.quizzesDir, filename))
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- defer file.Close()
|
|
|
-
|
|
|
- _, err = io.Copy(file, &buffer)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- return &meta, nil
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) createOrUpdateMarkdownFile(quiz *models.Quiz) error {
|
|
|
- markdown, err := MarkdownFromQuiz(quiz)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- fn, _ := s.GetQuizPath(quiz)
|
|
|
- if fn == "" {
|
|
|
- fn = filepath.Join(s.quizzesDir, fmt.Sprintf("quiz_%v.%s", quiz.ID, "md"))
|
|
|
- }
|
|
|
-
|
|
|
- file, err := os.Create(fn)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- defer file.Close()
|
|
|
-
|
|
|
- markdownWithMetaHeader, err := addMetaHeaderToMarkdown(markdown, &quiz.Meta)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- _, err = file.Write([]byte(markdownWithMetaHeader))
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- s.SetQuizPath(quiz, fn)
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-func (s *FileProboCollectorStore) createOrUpdateCollectionFile(collection *models.Collection) error {
|
|
|
- json, err := json.Marshal(collection)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- fn, _ := s.GetCollectionPath(collection)
|
|
|
- if fn == "" {
|
|
|
- fn = filepath.Join(s.collectionsDir, fmt.Sprintf("collection_%v.%s", collection.ID, "json"))
|
|
|
- }
|
|
|
-
|
|
|
- file, err := os.Create(fn)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- defer file.Close()
|
|
|
-
|
|
|
- _, err = file.Write([]byte(json))
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- s.SetCollectionPath(collection, fn)
|
|
|
-
|
|
|
- return nil
|
|
|
-}
|
|
|
-func addMetaHeaderToMarkdown(content string, meta *models.Meta) (string, error) {
|
|
|
- var buffer bytes.Buffer
|
|
|
-
|
|
|
- header, err := yaml.Marshal(meta)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
- _, err = buffer.WriteString("---\n" + string(header) + "---\n")
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
-
|
|
|
- _, err = buffer.WriteString(content)
|
|
|
- if err != nil {
|
|
|
- return "", err
|
|
|
- }
|
|
|
-
|
|
|
- return buffer.String(), nil
|
|
|
-}
|
|
|
-
|
|
|
-func parseMetaHeaderFromMarkdown(markdown string) (*models.Meta, string, error) {
|
|
|
- reader := strings.NewReader(markdown)
|
|
|
- var sb strings.Builder
|
|
|
- var line string
|
|
|
- var err error
|
|
|
- for {
|
|
|
- line, err = readLine(reader)
|
|
|
- if err != nil {
|
|
|
- if err == io.EOF {
|
|
|
- break
|
|
|
- }
|
|
|
- return nil, "", err
|
|
|
- }
|
|
|
-
|
|
|
- if strings.TrimSpace(line) == "---" {
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for {
|
|
|
- line, err = readLine(reader)
|
|
|
- if err != nil {
|
|
|
- if err == io.EOF {
|
|
|
- break
|
|
|
- }
|
|
|
- return nil, "", err
|
|
|
- }
|
|
|
-
|
|
|
- if strings.TrimSpace(line) == "---" {
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- sb.WriteString(line)
|
|
|
- }
|
|
|
-
|
|
|
- if sb.String() == "" {
|
|
|
- return nil, markdown, nil
|
|
|
- }
|
|
|
-
|
|
|
- var meta models.Meta
|
|
|
- err = yaml.Unmarshal([]byte(sb.String()), &meta)
|
|
|
- if err != nil {
|
|
|
- return nil, markdown, err
|
|
|
- }
|
|
|
-
|
|
|
- remainingMarkdown := markdown[strings.Index(markdown, "---\n"+sb.String()+"---\n")+len("---\n"+sb.String()+"---\n"):]
|
|
|
-
|
|
|
- return &meta, remainingMarkdown, nil
|
|
|
-}
|
|
|
-
|
|
|
-func readLine(reader *strings.Reader) (string, error) {
|
|
|
- var sb strings.Builder
|
|
|
- for {
|
|
|
- r, _, err := reader.ReadRune()
|
|
|
- if err != nil {
|
|
|
- if err == io.EOF {
|
|
|
- return sb.String(), io.EOF
|
|
|
- }
|
|
|
- return "", err
|
|
|
- }
|
|
|
-
|
|
|
- sb.WriteRune(r)
|
|
|
- if r == '\n' {
|
|
|
- break
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return sb.String(), nil
|
|
|
-}
|
|
|
-
|
|
|
-func writeMetaHeader(filename string, meta *models.Meta) (*models.Meta, error) {
|
|
|
- // Apri il file in lettura
|
|
|
- file, err := os.Open(filename)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- defer file.Close()
|
|
|
-
|
|
|
- // Crea un buffer in memoria
|
|
|
- var buffer bytes.Buffer
|
|
|
-
|
|
|
- // Scrivi l'intestazione YAML nel buffer
|
|
|
- header, err := yaml.Marshal(meta)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- _, err = buffer.WriteString("---\n" + string(header) + "---\n")
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Copia il contenuto del file originale nel buffer
|
|
|
- _, err = io.Copy(&buffer, file)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- // Riapri il file in scrittura
|
|
|
- file, err = os.Create(filename)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- defer file.Close()
|
|
|
-
|
|
|
- // Scrivi il contenuto del buffer nel file
|
|
|
- _, err = io.Copy(file, &buffer)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
-
|
|
|
- return meta, nil
|
|
|
-}
|