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 }