sync: Report custom errors
This commit is contained in:
parent
08ea1bac0d
commit
c78545c18b
17 changed files with 510 additions and 137 deletions
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue