/
plamolinux-http.go
178 lines (139 loc) · 4.34 KB
/
plamolinux-http.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
package sources
import (
"errors"
"fmt"
"net/url"
"path"
"path/filepath"
"slices"
"strconv"
"strings"
"gopkg.in/antchfx/htmlquery.v1"
"github.com/lxc/distrobuilder/shared"
)
type plamolinux struct {
common
}
// Run downloads Plamo Linux.
func (s *plamolinux) Run() error {
releaseStr := strings.TrimSuffix(s.definition.Image.Release, ".x")
release, err := strconv.Atoi(releaseStr)
if err != nil {
return fmt.Errorf("Failed to convert %q: %w", releaseStr, err)
}
u, err := url.Parse(s.definition.Source.URL)
if err != nil {
return fmt.Errorf("Failed to parse %q: %w", s.definition.Source.URL, err)
}
mirrorPath := path.Join(u.Path, fmt.Sprintf("Plamo-%s.x", releaseStr),
s.definition.Image.ArchitectureMapped, "plamo")
paths := []string{path.Join(mirrorPath, "00_base")}
ignoredPkgs := []string{"alsa_utils", "grub", "kernel", "lilo", "linux_firmware", "microcode_ctl",
"linux_firmwares", "cpufreqd", "cpufrequtils", "gpm", "ntp", "kmod", "kmscon"}
if release < 7 {
paths = append(paths, path.Join(mirrorPath, "01_minimum"))
}
var pkgDir string
for _, p := range paths {
u.Path = p
pkgDir, err = s.downloadFiles(s.definition.Image, u.String(), ignoredPkgs)
if err != nil {
return fmt.Errorf("Failed to download packages: %w", err)
}
}
var pkgTool string
// Find package tool
if release < 7 {
pkgTool = "hdsetup"
} else {
pkgTool = "pkgtools8"
}
matches, err := filepath.Glob(filepath.Join(pkgDir, fmt.Sprintf("%s-*.t*z*", pkgTool)))
if err != nil {
return fmt.Errorf("Failed to match pattern: %w", err)
}
if len(matches) == 0 {
return errors.New("Couldn't find any matching package")
} else if len(matches) > 1 {
return errors.New("Found more than one matching package")
}
err = shared.RunCommand(s.ctx, nil, nil, "tar", "-pxf", matches[0], "-C", pkgDir, "sbin/")
if err != nil {
return fmt.Errorf("Failed to unpack %q: %w", matches[0], err)
}
rootfsDirAbs, err := filepath.Abs(s.rootfsDir)
if err != nil {
return fmt.Errorf("Failed to get absolute path: %w", err)
}
err = shared.RunScript(s.ctx, fmt.Sprintf(`#!/bin/sh
set -eux
# Input variables
PKG_DIR="%s"
ROOTFS_DIR="%s"
# Environment
export PATH="${PATH}:${PKG_DIR}/sbin:${PKG_DIR}/sbin/installer"
export LC_ALL="C"
export LANG="C"
# Fix name of installer directory
if [ -d "${PKG_DIR}/sbin/installer_new" ]; then
[ -d "${PKG_DIR}/sbin/installer" ] && rm -r "${PKG_DIR}/sbin/installer"
mv "${PKG_DIR}/sbin/installer_new" "${PKG_DIR}/sbin/installer"
fi
# Fix filename of pkgtools8 files
pkg_scripts="installpkg installpkg2 installpkg2.mes makepkg updatepkg removepkg"
for s in $pkg_scripts
do
if [ -f "${PKG_DIR}/sbin/new_$s" ]; then
( cd "${PKG_DIR}/sbin" && mv new_"$s" $s )
fi
done
# generate symblic link to static-zstd
( cd "${PKG_DIR}/sbin/installer" && ln -sf zstd-* zstd )
# Don't call ldconfig
sed -i "/ldconfig/!s@/sbin@${PKG_DIR}&@g" ${PKG_DIR}/sbin/installpkg*
# Don't override PATH
sed -i "/^export PATH/d" ${PKG_DIR}/sbin/installpkg*
# Install all packages
for pkg in $(ls -cr ${PKG_DIR}/*.t*z*); do
installpkg -root ${ROOTFS_DIR} -priority ADD ${pkg}
done
`, pkgDir, rootfsDirAbs))
if err != nil {
return fmt.Errorf("Failed to run script: %w", err)
}
return nil
}
func (s *plamolinux) downloadFiles(def shared.DefinitionImage, URL string, ignoredPkgs []string) (string, error) {
doc, err := htmlquery.LoadURL(URL)
if err != nil {
return "", fmt.Errorf("Failed to load URL %q: %w", URL, err)
}
if doc == nil {
return "", errors.New("Empty HTML document")
}
nodes := htmlquery.Find(doc, `//a/@href`)
var dir string
for _, n := range nodes {
target := htmlquery.InnerText(n)
if strings.HasSuffix(target, ".txz") || strings.HasSuffix(target, ".tzst") {
pkgName := strings.Split(target, "-")[0]
if slices.Contains(ignoredPkgs, pkgName) {
continue
}
// package
dir, err = s.DownloadHash(def, fmt.Sprintf("%s/%s", URL, target), "", nil)
if err != nil {
return "", fmt.Errorf("Failed to download %q: %w", fmt.Sprintf("%s/%s", URL, target), err)
}
} else if strings.HasSuffix(target, ".txz/") || strings.HasSuffix(target, ".tzst/") {
// directory
u, err := url.Parse(URL)
if err != nil {
return "", fmt.Errorf("Failed to parse %q: %w", URL, err)
}
u.Path = path.Join(u.Path, target)
return s.downloadFiles(def, u.String(), ignoredPkgs)
}
}
return dir, nil
}