Compare commits
4 commits
c55d3478dd
...
aaaad3e348
Author | SHA1 | Date | |
---|---|---|---|
Lilian Jónsdóttir | aaaad3e348 | ||
Lilian Jónsdóttir | 5f7df27d76 | ||
Lilian Jónsdóttir | c9eaba2737 | ||
Lilian Jónsdóttir | 636c6f9143 |
|
@ -17,6 +17,7 @@ type config struct {
|
||||||
modsdir, infile, outfile string
|
modsdir, infile, outfile string
|
||||||
mods modlist.Modlist
|
mods modlist.Modlist
|
||||||
clobber, addmissing bool
|
clobber, addmissing bool
|
||||||
|
missingstate, ignoreuninstalled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var cfg config
|
var cfg config
|
||||||
|
@ -44,7 +45,7 @@ func main() {
|
||||||
app := &cli.App{
|
app := &cli.App{
|
||||||
Name: "fml",
|
Name: "fml",
|
||||||
Usage: "very simple modlist editor for factorio",
|
Usage: "very simple modlist editor for factorio",
|
||||||
Version: "v0.0.1",
|
Version: "v0.0.2",
|
||||||
Authors: []*cli.Author{{
|
Authors: []*cli.Author{{
|
||||||
Name: "Lilian Jónsdóttir",
|
Name: "Lilian Jónsdóttir",
|
||||||
Email: "lilian.jonsdottir@gmail.com",
|
Email: "lilian.jonsdottir@gmail.com",
|
||||||
|
@ -79,6 +80,18 @@ func main() {
|
||||||
Required: false,
|
Required: false,
|
||||||
Usage: "don't automatically add mods missing from infile",
|
Usage: "don't automatically add mods missing from infile",
|
||||||
},
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "enable-missing",
|
||||||
|
Aliases: []string{"e"},
|
||||||
|
Required: false,
|
||||||
|
Usage: "Missing mods are added in enabled state",
|
||||||
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
|
Name: "ignore-uninstalled",
|
||||||
|
Aliases: []string{"u"},
|
||||||
|
Required: false,
|
||||||
|
Usage: "Missing mod archives are ignored",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Before: func(ctx *cli.Context) error {
|
Before: func(ctx *cli.Context) error {
|
||||||
// Setup logger
|
// Setup logger
|
||||||
|
@ -93,6 +106,8 @@ func main() {
|
||||||
// Bool flags
|
// Bool flags
|
||||||
cfg.clobber = ctx.Bool("clobber")
|
cfg.clobber = ctx.Bool("clobber")
|
||||||
cfg.addmissing = !ctx.Bool("no-add-missing")
|
cfg.addmissing = !ctx.Bool("no-add-missing")
|
||||||
|
cfg.missingstate = ctx.Bool("enable-missing")
|
||||||
|
cfg.ignoreuninstalled = ctx.Bool("ignore-uninstalled")
|
||||||
|
|
||||||
// Deal with in/out file
|
// Deal with in/out file
|
||||||
var in = ctx.String("infile")
|
var in = ctx.String("infile")
|
||||||
|
@ -118,13 +133,20 @@ func main() {
|
||||||
Action: func(ctx *cli.Context) error {
|
Action: func(ctx *cli.Context) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
cfg.mods, err = modlist.ReadFromFile(cfg.infile)
|
cfg.mods, err = modlist.ReadFromFile(cfg.infile, cfg.modsdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.addmissing {
|
if cfg.addmissing {
|
||||||
err = modlist.AddModsNotInList(cfg.modsdir, &cfg.mods)
|
err = cfg.mods.AddModsNotInList(cfg.missingstate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cfg.ignoreuninstalled {
|
||||||
|
err = cfg.mods.RemoveModsNotInFolder()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ type Mod struct {
|
||||||
|
|
||||||
// Modlist holds a slice of mods.
|
// Modlist holds a slice of mods.
|
||||||
type Modlist struct {
|
type Modlist struct {
|
||||||
|
dir string
|
||||||
Mods []Mod `json:"mods"`
|
Mods []Mod `json:"mods"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,8 +120,73 @@ func (modlist *Modlist) String() {
|
||||||
modlist.Print("mods")
|
modlist.Print("mods")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddModsNotInList finds mod archives in the mod folder that aren't in the modlist, and adds them.
|
||||||
|
func (modlist *Modlist) AddModsNotInList(state bool) error {
|
||||||
|
r := regexp.MustCompile(fileRegex)
|
||||||
|
|
||||||
|
files, err := os.ReadDir(modlist.dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if strings.HasSuffix(file.Name(), ".zip") && !file.IsDir() {
|
||||||
|
groups := r.FindAllStringSubmatch(file.Name(), -1)
|
||||||
|
name := groups[0][1]
|
||||||
|
version := groups[0][2]
|
||||||
|
|
||||||
|
if !modlist.HasMod(name) {
|
||||||
|
log.Infof("Found %s not in modlist, adding v%s in disabled state.", name, version)
|
||||||
|
modlist.Mods = append(modlist.Mods, Mod{
|
||||||
|
Name: name,
|
||||||
|
Enabled: state,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveModsNotInFolder removes mods from the modlist if a corresponding
|
||||||
|
// zip file cannot be found in the mods dir.
|
||||||
|
func (modlist *Modlist) RemoveModsNotInFolder() error {
|
||||||
|
for i, mod := range modlist.Mods {
|
||||||
|
in, err := isModInFolder(mod.Name, modlist.dir)
|
||||||
|
if !in && err == nil {
|
||||||
|
log.Warnf("Zip file for %s could not be found, removing!", mod.Name)
|
||||||
|
// mods.Mods[i] = nil
|
||||||
|
modlist.Mods = append(modlist.Mods[:i], modlist.Mods[i+1:]...)
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
/// Functions related to the modlist but that shouldn't be attached to the types
|
/// Functions related to the modlist but that shouldn't be attached to the types
|
||||||
|
|
||||||
|
func isModInFolder(modname, modsdir string) (bool, error) {
|
||||||
|
if modname == "base" {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: try for less O(n)
|
||||||
|
files, err := os.ReadDir(modsdir)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if strings.HasPrefix(file.Name(), modname) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
// WriteToFile writes the modlist to the given filename.
|
// WriteToFile writes the modlist to the given filename.
|
||||||
func WriteToFile(filename string, mods *Modlist) error {
|
func WriteToFile(filename string, mods *Modlist) error {
|
||||||
data, err := json.MarshalIndent(&mods, "", " ")
|
data, err := json.MarshalIndent(&mods, "", " ")
|
||||||
|
@ -134,8 +200,10 @@ func WriteToFile(filename string, mods *Modlist) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFromFile reads the modlist from the given filename.
|
// ReadFromFile reads the modlist from the given filename.
|
||||||
func ReadFromFile(filename string) (Modlist, error) {
|
func ReadFromFile(filename, modsdir string) (Modlist, error) {
|
||||||
var mods Modlist = Modlist{}
|
var mods Modlist = Modlist{
|
||||||
|
dir: modsdir,
|
||||||
|
}
|
||||||
|
|
||||||
data, err := os.ReadFile(filename)
|
data, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -150,31 +218,3 @@ func ReadFromFile(filename string) (Modlist, error) {
|
||||||
log.Infof("Read modlist from file %s.", filename)
|
log.Infof("Read modlist from file %s.", filename)
|
||||||
return mods, nil
|
return mods, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddModsNotInList finds mod archives in the mod folder that aren't in the modlist, and adds them.
|
|
||||||
func AddModsNotInList(modsdir string, mods *Modlist) error {
|
|
||||||
r := regexp.MustCompile(fileRegex)
|
|
||||||
|
|
||||||
files, err := os.ReadDir(modsdir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range files {
|
|
||||||
if strings.HasSuffix(file.Name(), ".zip") && !file.IsDir() {
|
|
||||||
groups := r.FindAllStringSubmatch(file.Name(), -1)
|
|
||||||
name := groups[0][1]
|
|
||||||
version := groups[0][2]
|
|
||||||
|
|
||||||
if !mods.HasMod(name) {
|
|
||||||
log.Info("Found %s not in modlist, adding v%s in disabled state.", name, version)
|
|
||||||
mods.Mods = append(mods.Mods, Mod{
|
|
||||||
Name: name,
|
|
||||||
Enabled: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue