initial
This commit is contained in:
commit
8d15fa9731
9 changed files with 287 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
mix.lock
|
||||||
|
*.mix.hjson
|
||||||
|
*.exe
|
11
README.md
Normal file
11
README.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# 🍜 mix
|
||||||
|
> ` a declerative file-based package manager for windows.`
|
||||||
|
|
||||||
|
|
||||||
|
## features
|
||||||
|
- uses winget 😭
|
||||||
|
|
||||||
|
## requirements
|
||||||
|
- windows 10+ ofc
|
||||||
|
- recent version of [Go](https://golang.org/)
|
||||||
|
- [winget](https://github.com/microsoft/winget-cli)
|
115
cmd/sync.go
Normal file
115
cmd/sync.go
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"git.iwakura.rip/grng/mix/mix"
|
||||||
|
"github.com/urfave/cli/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
var SyncCommand = &cli.Command{
|
||||||
|
Name: "sync",
|
||||||
|
Action: func(context.Context, *cli.Command) error {
|
||||||
|
config := mix.Config
|
||||||
|
if len(config) == 0 {
|
||||||
|
return cli.Exit("No configuration files found", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mix.Lock == nil {
|
||||||
|
return cli.Exit("No lockfile found", 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg mix.MixConfig
|
||||||
|
for _, c := range config {
|
||||||
|
cfg = c
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
desired := make(map[string]mix.MixPackage)
|
||||||
|
for _, group := range cfg {
|
||||||
|
for _, pkg := range group.Packages {
|
||||||
|
desired[pkg.Id] = pkg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var newLock mix.MixLock
|
||||||
|
for _, lockPkg := range mix.Lock {
|
||||||
|
if _, ok := desired[lockPkg.Id]; !ok {
|
||||||
|
rmPackage(lockPkg.Id)
|
||||||
|
} else {
|
||||||
|
newLock = append(newLock, lockPkg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mix.Lock = newLock
|
||||||
|
|
||||||
|
for _, pkg := range desired {
|
||||||
|
found := false
|
||||||
|
for _, lockPkg := range mix.Lock {
|
||||||
|
if lockPkg.Id == pkg.Id {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
err := syncPackage(pkg)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to add package %s: %w", pkg.Id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mix.SaveLockFile()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to save lock file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func syncPackage(pkg mix.MixPackage) error {
|
||||||
|
isInstalled := false
|
||||||
|
for _, lockPkg := range mix.Lock {
|
||||||
|
if lockPkg.Id == pkg.Id {
|
||||||
|
isInstalled = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isInstalled {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Installing package %s...\n", pkg.Id)
|
||||||
|
cmd := exec.Command("winget", "install", "-h", "-e", "--id", pkg.Id, "-v", pkg.Version)
|
||||||
|
cmd.Stdout = nil
|
||||||
|
cmd.Stderr = nil
|
||||||
|
err := cmd.Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to install package %s: %w", pkg.Id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Package %s installed successfully!\n", pkg.Id)
|
||||||
|
mix.Lock = append(mix.Lock, mix.MixLockPackage{
|
||||||
|
Id: pkg.Id,
|
||||||
|
Version: pkg.Version,
|
||||||
|
})
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func rmPackage(id string) {
|
||||||
|
fmt.Printf("Removing package %s...\n", id)
|
||||||
|
cmd := exec.Command("winget", "uninstall", "-h", "-e", "--id", id)
|
||||||
|
cmd.Stdout = nil
|
||||||
|
cmd.Stderr = nil
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to uninstall package %s: %v\n", id, err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Package %s removed successfully!\n", id)
|
||||||
|
}
|
||||||
|
}
|
8
go.mod
Normal file
8
go.mod
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
module git.iwakura.rip/grng/mix
|
||||||
|
|
||||||
|
go 1.23.4
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/hjson/hjson-go/v4 v4.5.0 // indirect
|
||||||
|
github.com/urfave/cli/v3 v3.3.8 // indirect
|
||||||
|
)
|
4
go.sum
Normal file
4
go.sum
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
github.com/hjson/hjson-go/v4 v4.5.0 h1:ZHLiZ+HaGqPOtEe8T6qY8QHnoEsAeBv8wqxniQAp+CY=
|
||||||
|
github.com/hjson/hjson-go/v4 v4.5.0/go.mod h1:4zx6c7Y0vWcm8IRyVoQJUHAPJLXLvbG6X8nk1RLigSo=
|
||||||
|
github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E=
|
||||||
|
github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo=
|
17
main.go
Normal file
17
main.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.iwakura.rip/grng/mix/cmd"
|
||||||
|
"github.com/urfave/cli/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
(&cli.Command{
|
||||||
|
Commands: []*cli.Command{
|
||||||
|
cmd.SyncCommand,
|
||||||
|
},
|
||||||
|
}).Run(context.Background(), os.Args)
|
||||||
|
}
|
21
mix.hjson.example
Normal file
21
mix.hjson.example
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
default: {
|
||||||
|
packages: [
|
||||||
|
{
|
||||||
|
id: "wez.wezterm"
|
||||||
|
version: "20240203-110809-5046fc22"
|
||||||
|
config: [
|
||||||
|
{
|
||||||
|
type: "raw"
|
||||||
|
path: "~/.wezterm.lua"
|
||||||
|
data:
|
||||||
|
'''
|
||||||
|
local wezterm = require 'wezterm'
|
||||||
|
local config = {}
|
||||||
|
config.color_scheme = 'Batman'
|
||||||
|
return config
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
1
mix.lock.example
Normal file
1
mix.lock.example
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[]
|
107
mix/files.go
Normal file
107
mix/files.go
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
package mix
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
hjson "github.com/hjson/hjson-go/v4"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Config = ConfigFiles()
|
||||||
|
var Lock = LockFile()
|
||||||
|
|
||||||
|
// *.mix.hjson
|
||||||
|
func ConfigFiles() map[string]MixConfig {
|
||||||
|
dir, err := os.ReadDir(".")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
files := []string{}
|
||||||
|
|
||||||
|
for _, file := range dir {
|
||||||
|
if file.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(file.Name(), ".mix.hjson") {
|
||||||
|
files = append(files, file.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config := make(map[string]MixConfig)
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
f, err := os.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg MixConfig
|
||||||
|
err = hjson.Unmarshal(f, &cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cfg) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
config[file] = cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func SaveLockFile() error {
|
||||||
|
data, err := hjson.Marshal(Lock)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile("mix.lock", data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type MixConfig map[string]MixGroup
|
||||||
|
|
||||||
|
type MixGroup struct {
|
||||||
|
Packages []MixPackage `json:"packages"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MixPackage struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Config []MixPackageConfig `json:"config"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MixPackageConfig struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
Data interface{} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func LockFile() MixLock {
|
||||||
|
file, err := os.ReadFile("mix.lock")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var lock MixLock
|
||||||
|
err = hjson.Unmarshal(file, &lock)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return lock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MixLock []MixLockPackage
|
||||||
|
type MixLockPackage struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue