~hristoast/openmw-validator

f526688a0494cf059d64e19a4b86ee0aa35a071a — Hristos N. Triantafillou 29 days ago 9410c95 0.6
Report on groundcover files
4 files changed, 92 insertions(+), 46 deletions(-)

M config.go
M files.go
M paths.go
M validations.go
M config.go => config.go +22 -14
@@ 14,24 14,27 @@ import (

// Represents data extracted from a given openmw.cfg file.
type cfgData struct {
	contentFiles []string
	dataPaths    []string
	contentFiles     []string
	groundcoverFiles []string
	dataPaths        []string
}

// Processed configuration for a given openmw.cfg file.
type gameConfig struct {
	dataDirs       []*dataDir
	contentFiles   []*contentFile
	replacedFiles  []*replacedFile
	dataFiles      map[string]*dataFile
	foundPlugins   []string
	badPaths       []string
	bunkContent    []string
	duplicatePaths []string
	emptyPaths     []string
	foundPaths     map[string]bool
	runCfg         *runConfig
	fullyReplaced  []*dataDir
	dataDirs         []*dataDir
	contentFiles     []*contentFile
	groundcoverFiles []*contentFile
	replacedFiles    []*replacedFile
	dataFiles        map[string]*dataFile
	foundPlugins     []string
	badPaths         []string
	bunkContent      []string
	bunkGroundcover  []string
	duplicatePaths   []string
	emptyPaths       []string
	foundPaths       map[string]bool
	runCfg           *runConfig
	fullyReplaced    []*dataDir
}

// Check a single path and return all files within it that were replaced.


@@ 114,8 117,12 @@ func readCfgFile(filePath string) cfgData {
	splitData := strings.Split(string(data), "\n")
	contentFiles := make([]string, 0)
	dataPaths := make([]string, 0)
	groundcover := make([]string, 0)

	for _, line := range splitData {
		if strings.HasPrefix(line, "groundcover=") {
			groundcover = append(groundcover, string(line))
		}
		if strings.HasPrefix(line, "data=") {
			dataPaths = append(dataPaths, string(line))
		}


@@ 126,6 133,7 @@ func readCfgFile(filePath string) cfgData {

	d.contentFiles = contentFiles
	d.dataPaths = dataPaths
	d.groundcoverFiles = groundcover

	return d
}

M files.go => files.go +34 -11
@@ 49,9 49,17 @@ type replacedFile struct {
	replacedBy *dataDir
}

func checkContentFile(cf string, order int, gc *gameConfig) bool {
func checkContentFile(cf string, order int, gc *gameConfig, groundcover bool) bool {
	// Format the file...
	c := sanitizePath(cf, "content=")
	var c string
	var fileType string
	if groundcover {
		fileType = "groundcover"
		c = sanitizePath(cf, "groundcover=")
	} else {
		fileType = "content"
		c = sanitizePath(cf, "content=")
	}

	if !gc.runCfg.quiet {
		log.Printf("Checking: %v", c)


@@ 67,19 75,34 @@ func checkContentFile(cf string, order int, gc *gameConfig) bool {
	}

	if exists {
		gc.contentFiles = append(gc.contentFiles, &contentFile{
			file: &dataFile{
				dDir:      &dataDir{},
				localPath: "",
			},
			order: 0,
		})
		if groundcover {
			gc.groundcoverFiles = append(gc.groundcoverFiles, &contentFile{
				file: &dataFile{
					dDir:      &dataDir{},
					localPath: "",
				},
				order: 0,
			})

		} else {
			gc.contentFiles = append(gc.contentFiles, &contentFile{
				file: &dataFile{
					dDir:      &dataDir{},
					localPath: "",
				},
				order: 0,
			})
		}

	} else {
		if !gc.runCfg.quiet {
			log.Printf("The content file \"%s\" doesn't exist in any configured data path!", c)
			log.Printf("The %s file \"%s\" doesn't exist in any configured data path!", fileType, c)
		}
		if groundcover {
			gc.bunkGroundcover = append(gc.bunkGroundcover, c)
		} else {
			gc.bunkContent = append(gc.bunkContent, c)
		}
		gc.bunkContent = append(gc.bunkContent, c)
		return false
	}
	return true

M paths.go => paths.go +6 -5
@@ 10,11 10,12 @@ import (

// Represents attributes related to a configured data path.
type dataDir struct {
	files    []*dataFile
	plugins  []*dataFile
	order    int
	path     string
	replaced int
	files       []*dataFile
	groundcover []*dataFile
	plugins     []*dataFile
	order       int
	path        string
	replaced    int
}

// Do `filepath.Walk` on a dataDir's paths and register found files as needed.

M validations.go => validations.go +30 -16
@@ 26,18 26,19 @@ func runValidations(runCfg *runConfig) {
	dataDirCount := 1
	d := readCfgFile(runCfg.cfg)
	g := &gameConfig{
		dataDirs:       []*dataDir{},
		contentFiles:   []*contentFile{},
		replacedFiles:  []*replacedFile{},
		dataFiles:      map[string]*dataFile{},
		foundPlugins:   []string{},
		badPaths:       []string{},
		bunkContent:    []string{},
		duplicatePaths: []string{},
		emptyPaths:     []string{},
		foundPaths:     map[string]bool{},
		runCfg:         runCfg,
		fullyReplaced:  []*dataDir{},
		dataDirs:         []*dataDir{},
		contentFiles:     []*contentFile{},
		groundcoverFiles: []*contentFile{},
		replacedFiles:    []*replacedFile{},
		dataFiles:        map[string]*dataFile{},
		foundPlugins:     []string{},
		badPaths:         []string{},
		bunkContent:      []string{},
		duplicatePaths:   []string{},
		emptyPaths:       []string{},
		foundPaths:       map[string]bool{},
		runCfg:           runCfg,
		fullyReplaced:    []*dataDir{},
	}

	if len(d.contentFiles) == 0 || len(d.dataPaths) == 0 {


@@ 130,10 131,14 @@ func runValidations(runCfg *runConfig) {
		log.Println()
	}
	for _, c := range d.contentFiles {
		_ = checkContentFile(c, contentFileCount, g)
		_ = checkContentFile(c, contentFileCount, g, false)
		contentFileCount++
	}

	for _, c := range d.groundcoverFiles {
		_ = checkContentFile(c, 0, g, true)
	}

	log.Println()
	log.Printf("Total files found: %d", totalFiles)
	log.Printf("Total plugins found: %v", len(g.foundPlugins))


@@ 147,6 152,7 @@ func runValidations(runCfg *runConfig) {
	haveEmptyPaths := len(g.emptyPaths) > 0
	haveDupedPaths := dupeCount > 0
	haveBunkContent := len(g.bunkContent) > 0
	haveBunkGroundcover := len(g.bunkGroundcover) > 0
	haveFullyReplaced := len(g.fullyReplaced) > 0

	if haveBadPaths {


@@ 189,6 195,16 @@ func runValidations(runCfg *runConfig) {
		log.Println()
	}

	if haveBunkGroundcover {
		log.Printf("Bad groundcover files count: %v", len(g.bunkGroundcover))
		log.Println("The following groundcover files have been configured but are not readable:")
		log.Println()
		for _, gf := range g.bunkGroundcover {
			log.Println(gf)
		}
		log.Println()
	}

	if haveFullyReplaced {
		log.Printf("Fully replaced data path count: %v", len(g.fullyReplaced))
		log.Println("The following data paths are fully replaced:")


@@ 199,7 215,7 @@ func runValidations(runCfg *runConfig) {
		log.Println()
	}

	if !haveBadPaths && !haveEmptyPaths && !haveDupedPaths && !haveBunkContent && !haveFullyReplaced {
	if !haveBadPaths && !haveEmptyPaths && !haveDupedPaths && !haveBunkContent && !haveBunkGroundcover && !haveFullyReplaced {
		log.Println("Great Job! No problems detected.")
		log.Println()
	}


@@ 244,8 260,6 @@ func runValidations(runCfg *runConfig) {

	}

	//TODO: Check groundcover files with content files
	//TODO: Report if a data path is totally replaced
	//TODO: Report unused content files (ones found in data paths but not configured as content files)
	//TODO: Very quiet mode, that just exits 0 or 1
	//TODO: Tests for everything