server/admin/sync/exercice_files.go

87 lines
2.9 KiB
Go

package sync
import (
"encoding/hex"
"fmt"
"path"
"strings"
"unicode"
"srs.epita.fr/fic-server/libfic"
)
// SyncExerciceFiles reads the content of files/ directory and import it as EFile for the given challenge.
// It takes care of DIGESTS.txt and ensure imported files match.
func SyncExerciceFiles(i Importer, exercice fic.Exercice) (errs []string) {
// If no files directory, don't display error
if ! i.exists(path.Join(exercice.Path, "files")) {
return
}
if digs, err := getFileContent(i, path.Join(exercice.Path, "files", "DIGESTS.txt")); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to read DIGESTS.txt: %s", path.Base(exercice.Path), err))
} else if _, err := exercice.WipeFiles(); err != nil {
errs = append(errs, err.Error())
} else if files, err := i.listDir(path.Join(exercice.Path, "files")); err != nil {
errs = append(errs, err.Error())
} else {
// Parse DIGESTS.txt
digests := map[string][]byte{}
for nline, d := range strings.Split(digs, "\n") {
if dsplt := strings.SplitN(d, " ", 2); len(dsplt) != 2 {
errs = append(errs, fmt.Sprintf("%q: unable to parse DIGESTS.txt line %d: invalid format", path.Base(exercice.Path), nline + 1))
continue
} else if hash, err := hex.DecodeString(dsplt[0]); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to parse DIGESTS.txt line %d: %s", path.Base(exercice.Path), nline + 1, err))
continue
} else {
digests[strings.TrimLeftFunc(dsplt[1], unicode.IsSpace)] = hash
}
}
// Import splitted files
var splittedFiles []string
for _, fname := range files {
if matched, _ := path.Match("*.00", fname); matched {
fname = fname[:len(fname)-3]
splittedFiles = append(splittedFiles, fname + ".[0-9][0-9]")
files = append(files, fname)
} else if matched, _ := path.Match("*00", fname); matched {
fname = fname[:len(fname)-2]
splittedFiles = append(splittedFiles, fname + "[0-9][0-9]")
files = append(files, fname)
} else if matched, _ := path.Match("*_MERGED", fname); matched {
splittedFiles = append(splittedFiles, fname)
}
}
// Import standard files
for _, fname := range files {
if fname == "DIGESTS.txt" {
continue
}
foundSplitted := false
for _, sf := range splittedFiles {
if matched, _ := path.Match(sf, fname); matched {
foundSplitted = true
}
}
if foundSplitted {
continue
}
if f, err := i.importFile(path.Join(exercice.Path, "files", fname),
func(filePath string, origin string) (interface{}, error) {
return exercice.ImportFile(filePath, origin, digests[fname])
}); err != nil {
errs = append(errs, fmt.Sprintf("%q: unable to import file %q: %s", path.Base(exercice.Path), fname, err))
continue
} else if f.(fic.EFile).Size == 0 {
errs = append(errs, fmt.Sprintf("%q: WARNING imported file %q is empty!", path.Base(exercice.Path), fname))
}
}
}
return
}