Skip to content

Commit 8874796

Browse files
committed
feat: Add clean command and refactor profile handling in build command
1 parent 32dcebc commit 8874796

5 files changed

Lines changed: 160 additions & 28 deletions

File tree

alteriso/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ go 1.25.1
55
require (
66
github.com/Hayao0819/nahi v0.0.4-0.20250226153401-b90a5060c85a
77
github.com/m-mizutani/clog v0.1.0
8+
github.com/moby/sys/mount v0.3.4
9+
github.com/moby/sys/mountinfo v0.7.2
810
github.com/otiai10/copy v1.14.1
911
github.com/samber/lo v1.51.0
1012
github.com/spf13/cobra v1.8.1

alteriso/go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
2828
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
2929
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
3030
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
31+
github.com/moby/sys/mount v0.3.4 h1:yn5jq4STPztkkzSKpZkLcmjue+bZJ0u2AuQY1iNI1Ww=
32+
github.com/moby/sys/mount v0.3.4/go.mod h1:KcQJMbQdJHPlq5lcYT+/CjatWM4PuxKe+XLSVS4J6Os=
33+
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
34+
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
3135
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
3236
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
3337
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=

alteriso/src/internal/cmd/clean.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package cmd
2+
3+
import (
4+
"log/slog"
5+
"os"
6+
"path/filepath"
7+
"strings"
8+
9+
"github.com/FascodeNet/alterlinux/src/internal/errors"
10+
"github.com/Hayao0819/nahi/futils"
11+
"github.com/moby/sys/mount"
12+
"github.com/moby/sys/mountinfo"
13+
"github.com/spf13/cobra"
14+
)
15+
16+
func correctWorkDir(dir string) (string, bool) {
17+
if !futils.IsDir(dir) {
18+
return "", false
19+
}
20+
21+
// TODO: 適切に判断する
22+
return dir, true
23+
}
24+
25+
func mountedDirsIn(dir string) []string {
26+
mounts, err := mountinfo.GetMounts(func(i *mountinfo.Info) (skip bool, stop bool) {
27+
mp := filepath.Clean(i.Mountpoint)
28+
parentDir := filepath.Clean(dir) + string(filepath.Separator)
29+
if mp == parentDir || strings.HasPrefix(mp+string(filepath.Separator), parentDir) {
30+
return false, false
31+
}
32+
return true, false
33+
})
34+
if err != nil {
35+
return nil
36+
}
37+
38+
var mountedDirs []string
39+
for _, m := range mounts {
40+
mountedDirs = append(mountedDirs, m.Mountpoint)
41+
}
42+
return mountedDirs
43+
}
44+
45+
func cleanCmd() *cobra.Command {
46+
workDir := "./work"
47+
cmd := cobra.Command{
48+
Use: "clean",
49+
Short: "Clean up working directories",
50+
RunE: func(cmd *cobra.Command, args []string) error {
51+
52+
correctedWorkDir, ok := correctWorkDir(workDir)
53+
if !ok {
54+
return errors.Newf("workdir %s is not a valid directory", workDir)
55+
}
56+
workDir = correctedWorkDir
57+
58+
var failed bool
59+
mountedDirs := mountedDirsIn(correctedWorkDir)
60+
for _, dir := range mountedDirs {
61+
if err := mount.Unmount(dir); err != nil {
62+
slog.Error("Failed to unmount dir", "dir", dir, "error", err)
63+
failed = true
64+
}
65+
}
66+
if failed {
67+
return errors.Newf("failed to unmount some directories in %s", workDir)
68+
}
69+
70+
slog.Info("Removing working directory...", "dir", workDir)
71+
if err := os.RemoveAll(workDir); err != nil {
72+
return err
73+
}
74+
return nil
75+
76+
},
77+
}
78+
79+
// archisoの作業ディレクトリ
80+
cmd.Flags().StringVarP(&workDir, "workdir", "w", workDir, "Path to working directory of archiso")
81+
82+
return &cmd
83+
}
84+
85+
func init() {
86+
rootReg.Add(cleanCmd())
87+
}

alteriso/src/internal/cmd/profile/build.go

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,100 @@
11
package profile
22

33
import (
4-
"fmt"
54
"log/slog"
65
"os"
76
"path"
7+
"path/filepath"
88

99
"github.com/FascodeNet/alterlinux/src/internal/archiso"
1010
"github.com/FascodeNet/alterlinux/src/internal/errors"
1111
"github.com/Hayao0819/nahi/exutils"
1212
"github.com/spf13/cobra"
1313
)
1414

15+
func getProfileFromArg(cmd *cobra.Command, configDir string) (*archiso.Profile, error) {
16+
bootloadersPath := cmd.Parent().PersistentFlags().Lookup("bootloaders").Value.String()
17+
modulesPath := cmd.Parent().PersistentFlags().Lookup("modules").Value.String()
18+
19+
profile, err := archiso.NewProfile(configDir,
20+
archiso.WithModulesPath(modulesPath),
21+
archiso.WithbootloadersPath(bootloadersPath),
22+
)
23+
if err != nil {
24+
return nil, errors.Wrap(err)
25+
}
26+
27+
return profile, nil
28+
}
29+
1530
func buildCmd() *cobra.Command {
1631
outDir := "./out"
32+
workDir := "./work"
1733
cmd := cobra.Command{
1834
Use: "build",
1935
Short: "Build the ISO from generated profile",
20-
RunE: func(cmd *cobra.Command, args []string) error {
21-
configDir := args[0]
22-
configName := path.Base(configDir)
23-
24-
bootloadersPath := cmd.Parent().PersistentFlags().Lookup("bootloaders").Value.String()
25-
modulesPath := cmd.Parent().PersistentFlags().Lookup("modules").Value.String()
36+
PreRunE: func(cmd *cobra.Command, args []string) error {
37+
// TODO: 権限チェック
2638

27-
profile, err := archiso.NewProfile(configDir,
28-
archiso.WithModulesPath(modulesPath),
29-
archiso.WithbootloadersPath(bootloadersPath),
30-
)
31-
if err != nil {
32-
return err
39+
return nil
40+
},
41+
RunE: func(cmd *cobra.Command, args []string) error {
42+
// Load profile
43+
var configDir string
44+
if len(args) < 1 {
45+
configDir = "./configs/xfce"
46+
} else {
47+
configDir = args[0]
3348
}
3449

35-
profileDir, err := os.MkdirTemp("", fmt.Sprintf("alteriso-%s-*", configName))
50+
configName := path.Base(configDir)
51+
slog.Info("Loading profile...", "config", configDir)
52+
profile, err := getProfileFromArg(cmd, configDir)
3653
if err != nil {
3754
return errors.Wrap(err)
3855
}
39-
defer os.RemoveAll(profileDir)
56+
slog.Info("Using profile", "name", configName)
57+
58+
// Setup directories
59+
for _, dir := range []*string{&outDir, &workDir} {
60+
absDir, err := filepath.Abs(*dir)
61+
if err != nil {
62+
return errors.Wrap(err)
63+
}
64+
*dir = absDir
65+
if err := os.MkdirAll(*dir, 0o755); err != nil {
66+
return errors.Wrap(err)
67+
}
68+
}
69+
slog.Info("Output directory", "dir", outDir)
70+
slog.Info("Working directory", "dir", workDir)
4071

41-
if err := profile.GenArchisoProfile(profileDir); err != nil {
72+
// Generate archiso profile
73+
archisoprofileDir := path.Join(workDir, "profile")
74+
if err := profile.GenArchisoProfile(archisoprofileDir); err != nil {
4275
return errors.Wrap(err)
4376
}
77+
slog.Info("Generated archiso profile", "dir", archisoprofileDir)
4478

45-
slog.Info("Generated archiso profile", "dir", profileDir)
46-
47-
mkarchiso, err := archiso.MkarchisoPath()
79+
// Build ISO with mkarchiso
80+
// TODO: 権限昇格
81+
archisoWorkDir := path.Join(workDir, "archiso")
82+
if err := os.MkdirAll(archisoWorkDir, 0o755); err != nil {
83+
return errors.Wrap(err)
84+
}
85+
archisoPacmanCacheDir := path.Join(workDir, "pacman_cache")
86+
if err := os.MkdirAll(archisoPacmanCacheDir, 0o755); err != nil {
87+
return errors.Wrap(err)
88+
}
89+
mkarchisoPath, err := archiso.MkarchisoPath()
4890
if err != nil {
4991
return errors.Wrap(err)
5092
}
93+
mkarchisoCmd := exutils.CommandWithStdio(mkarchisoPath, "-v", "-w", archisoWorkDir, "-o", outDir, archisoprofileDir)
94+
mkarchisoCmd.Env = append(mkarchisoCmd.Env, "ALTERISO_PACMAN_CACHE="+archisoPacmanCacheDir)
95+
slog.Info("Building ISO image...", "command", mkarchisoCmd.String())
5196

52-
if err := exutils.CommandWithStdio(mkarchiso, "-v", "-w", "work", "-o", outDir, profileDir).Run(); err != nil {
97+
if err := mkarchisoCmd.Run(); err != nil {
5398
return errors.Wrap(err)
5499
}
55100

@@ -59,6 +104,7 @@ func buildCmd() *cobra.Command {
59104
}
60105

61106
cmd.Flags().StringVarP(&outDir, "out", "o", outDir, "Output directory")
107+
cmd.Flags().StringVar(&workDir, "work", workDir, "Working directory")
62108

63109
return &cmd
64110

alteriso/src/internal/cmd/profile/format.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package profile
22

33
import (
4-
"github.com/FascodeNet/alterlinux/src/internal/archiso"
54
"github.com/FascodeNet/alterlinux/src/internal/errors"
65
"github.com/Hayao0819/nahi/futils"
76
"github.com/spf13/cobra"
@@ -18,13 +17,7 @@ func profileFormatCmd() *cobra.Command {
1817
return errors.Newf("directory %s does not exist", configPath)
1918
}
2019

21-
bootloadersPath := cmd.Parent().PersistentFlags().Lookup("bootloaders").Value.String()
22-
modulesPath := cmd.Parent().PersistentFlags().Lookup("modules").Value.String()
23-
24-
profile, err := archiso.NewProfile(configPath,
25-
archiso.WithModulesPath(modulesPath),
26-
archiso.WithbootloadersPath(bootloadersPath),
27-
)
20+
profile, err := getProfileFromArg(cmd, configPath)
2821
if err != nil {
2922
return err
3023
}

0 commit comments

Comments
 (0)