sync: Report custom errors

This commit is contained in:
nemunaire 2022-07-11 19:57:33 +02:00
parent 08ea1bac0d
commit c78545c18b
17 changed files with 510 additions and 137 deletions

View file

@ -3,7 +3,6 @@ package sync
import (
"bytes"
"fmt"
"log"
"net/http"
"net/url"
"path"
@ -17,9 +16,6 @@ import (
"srs.epita.fr/fic-server/libfic"
)
// LogMissingResolution logs the absence of resolution.mp4 instead of returning an error.
var LogMissingResolution = false
func fixnbsp(s string) string {
return strings.Replace(strings.Replace(strings.Replace(s, " ?", " ?", -1), " !", " !", -1), " :", " :", -1)
}
@ -102,7 +98,7 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
var err error
eid, e.Title, err = parseExerciceDirname(edir)
if err != nil {
errs = append(errs, fmt.Errorf("unable to parse exercice directory: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("unable to parse exercice directory: %w", err), theme))
return nil, p, eid, edir, errs
}
@ -110,7 +106,7 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
if myTitle, err := GetFileContent(i, path.Join(epath, "title.txt")); err == nil {
myTitle = strings.TrimSpace(myTitle)
if strings.Contains(myTitle, "\n") {
errs = append(errs, fmt.Errorf("title.txt: Title can't contain new lines"))
errs = append(errs, NewExerciceError(e, fmt.Errorf("title.txt: Title can't contain new lines"), theme))
} else {
e.Title = myTitle
}
@ -128,20 +124,20 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
err = fmt.Errorf("Unable to find overview.txt nor overview.md")
}
if err != nil {
errs = append(errs, fmt.Errorf("overview.txt: %s", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("overview.txt: %s", err), theme))
} else {
e.Overview = fixnbsp(e.Overview)
var buf bytes.Buffer
err := goldmark.Convert([]byte(strings.Split(e.Overview, "\n")[0]), &buf)
if err != nil {
errs = append(errs, fmt.Errorf("overview.md: an error occurs during markdown formating of the headline: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("overview.md: an error occurs during markdown formating of the headline: %w", err), theme))
} else {
e.Headline = string(buf.Bytes())
}
if e.Overview, err = ProcessMarkdown(i, e.Overview, epath); err != nil {
errs = append(errs, fmt.Errorf("overview.md: an error occurs during markdown formating: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("overview.md: an error occurs during markdown formating: %w", err), theme))
}
}
@ -153,20 +149,20 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
err = fmt.Errorf("Unable to find statement.txt nor statement.md")
}
if err != nil {
errs = append(errs, fmt.Errorf("statement.md: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("statement.md: %w", err), theme))
} else {
if e.Statement, err = ProcessMarkdown(i, fixnbsp(e.Statement), epath); err != nil {
errs = append(errs, fmt.Errorf("statement.md: an error occurs during markdown formating: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("statement.md: an error occurs during markdown formating: %w", err), theme))
}
}
if i.exists(path.Join(epath, "finished.txt")) {
e.Finished, err = GetFileContent(i, path.Join(epath, "finished.txt"))
if err != nil {
errs = append(errs, fmt.Errorf("finished.txt: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("finished.txt: %w", err), theme))
} else {
if e.Finished, err = ProcessMarkdown(i, e.Finished, epath); err != nil {
errs = append(errs, fmt.Errorf("finished.txt: an error occurs during markdown formating: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("finished.txt: an error occurs during markdown formating: %w", err), theme))
}
}
}
@ -175,19 +171,19 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
var md toml.MetaData
p, md, err = parseExerciceParams(i, epath)
if err != nil {
errs = append(errs, fmt.Errorf("challenge.txt: %w", err))
errs = append(errs, NewChallengeTxtError(e, 0, err, theme))
return
}
// Alert about unknown keys in challenge.txt
if len(md.Undecoded()) > 0 {
for _, k := range md.Undecoded() {
errs = append(errs, fmt.Errorf("challenge.txt: unknown key %q found, check https://srs.nemunai.re/fic/files/challenge/", k))
errs = append(errs, NewChallengeTxtError(e, 0, fmt.Errorf("unknown key %q found, check https://srs.nemunai.re/fic/files/challenge/", k), theme))
}
}
if p.Gain == 0 {
errs = append(errs, fmt.Errorf("challenge.txt: Undefined gain for challenge"))
errs = append(errs, NewChallengeTxtError(e, 0, fmt.Errorf("Undefined gain for challenge"), theme))
} else {
e.Gain = p.Gain
}
@ -195,11 +191,11 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
// Handle dependency
if len(p.Dependencies) > 0 {
if len(p.Dependencies[0].Theme) > 0 && p.Dependencies[0].Theme != theme.Name {
errs = append(errs, fmt.Errorf("unable to treat dependency to another theme (%q): not implemented.", p.Dependencies[0].Theme))
errs = append(errs, NewExerciceError(e, fmt.Errorf("unable to treat dependency to another theme (%q): not implemented.", p.Dependencies[0].Theme), theme))
} else {
if dmap == nil {
if dmap2, err := buildDependancyMap(i, theme); err != nil {
errs = append(errs, fmt.Errorf("unable to build dependency map: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("unable to build dependency map: %w", err), theme))
} else {
dmap = &dmap2
}
@ -217,7 +213,7 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
for k, _ := range *dmap {
dmap_keys = append(dmap_keys, fmt.Sprintf("%d", k))
}
errs = append(errs, fmt.Errorf("Unable to find required exercice dependancy %d (available at time of processing: %s)", p.Dependencies[0].Id, strings.Join(dmap_keys, ",")))
errs = append(errs, NewExerciceError(e, fmt.Errorf("Unable to find required exercice dependancy %d (available at time of processing: %s)", p.Dependencies[0].Id, strings.Join(dmap_keys, ",")), theme))
}
}
}
@ -230,10 +226,10 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
if !i.exists(e.VideoURI) {
e.VideoURI = ""
} else if size, err := getFileSize(i, e.VideoURI); err != nil {
errs = append(errs, fmt.Errorf("resolution.mp4: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("resolution.mp4: %w", err), theme))
e.VideoURI = ""
} else if size == 0 {
errs = append(errs, fmt.Errorf("resolution.mp4: The file is empty!"))
errs = append(errs, NewExerciceError(e, fmt.Errorf("resolution.mp4: The file is empty!"), theme))
e.VideoURI = ""
} else {
e.VideoURI = strings.Replace(url.PathEscape(path.Join("$RFILES$", e.VideoURI)), "%2F", "/", -1)
@ -247,24 +243,20 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
if i.exists(writeup) {
if size, err := getFileSize(i, writeup); err != nil {
errs = append(errs, fmt.Errorf("resolution.md: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("resolution.md: %w", err), theme))
} else if size == 0 {
errs = append(errs, fmt.Errorf("resolution.md: The file is empty!"))
errs = append(errs, NewExerciceError(e, fmt.Errorf("resolution.md: The file is empty!"), theme))
} else if e.Resolution, err = GetFileContent(i, writeup); err != nil {
errs = append(errs, fmt.Errorf("resolution.md: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("resolution.md: %w", err), theme))
} else if e.Resolution, err = ProcessMarkdown(i, e.Resolution, epath); err != nil {
errs = append(errs, fmt.Errorf("resolution.md: error during markdown processing: %w", err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("resolution.md: error during markdown processing: %w", err), theme))
} else {
resolutionFound = true
}
}
if !resolutionFound {
if LogMissingResolution {
log.Printf("%q: no resolution video or text file found in %s", edir, epath)
} else {
errs = append(errs, fmt.Errorf("no resolution video or text file found in %s", epath))
}
errs = append(errs, NewExerciceError(e, ErrResolutionNotFound, theme))
}
return
@ -273,30 +265,29 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
// SyncExercice imports new or updates existing given exercice.
func SyncExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*fic.Exercice) (e *fic.Exercice, eid int, errs []error) {
var err error
var edir string
var p ExerciceParams
var berrors []error
e, p, eid, edir, berrors = BuildExercice(i, theme, epath, dmap)
e, p, eid, _, berrors = BuildExercice(i, theme, epath, dmap)
for _, e := range berrors {
errs = append(errs, fmt.Errorf("%q: %w", edir, e))
errs = append(errs, e)
}
if e != nil {
// Create or update the exercice
err = theme.SaveNamedExercice(e)
if err != nil {
errs = append(errs, fmt.Errorf("%q: error on exercice save: %w", edir, err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("error on exercice save: %w", err), theme))
return
}
// Import eercice tags
if _, err := e.WipeTags(); err != nil {
errs = append(errs, fmt.Errorf("%q: Unable to wipe tags: %w", edir, err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("unable to wipe tags: %w", err), theme))
}
for _, tag := range p.Tags {
if _, err := e.AddTag(tag); err != nil {
errs = append(errs, fmt.Errorf("%q: Unable to add tag: %w", edir, err))
errs = append(errs, NewExerciceError(e, fmt.Errorf("unable to add tag: %w", err), theme))
return
}
}