-
Notifications
You must be signed in to change notification settings - Fork 36
/
main.go
150 lines (126 loc) · 3.83 KB
/
main.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
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"runtime/pprof"
"strconv"
"github.com/clearlinux/mixer-tools/swupd"
)
func usage() {
log.Printf(`Create pack files using a swupd state directory
Usage:
create-pack [FLAGS] STATEDIR FROM_VERSION TO_VERSION BUNDLE
create-pack -all [FLAGS] STATEDIR FROM_VERSION TO_VERSION
Flags:
`)
flag.PrintDefaults()
os.Exit(2)
}
func main() {
log.SetFlags(0)
cpuProfile := flag.String("cpuprofile", "", "write CPU profile to a file")
useChroot := flag.Bool("chroot", false, "use chroot to speed up pack generation")
allBundles := flag.Bool("all", false, "create packs for all bundles new in TO version")
force := flag.Bool("f", false, "rewrite packs that already exist")
flag.Usage = usage
flag.Parse()
if (*allBundles && flag.NArg() != 3) || (!*allBundles && flag.NArg() != 4) {
usage()
}
if *cpuProfile != "" {
f, err := os.Create(*cpuProfile)
if err != nil {
log.Fatalf("couldn't create file for CPU profile: %s", err)
}
err = pprof.StartCPUProfile(f)
if err != nil {
log.Fatal(err)
}
defer pprof.StopCPUProfile()
}
stateDir := flag.Arg(0)
fromVersion := flag.Arg(1)
toVersion := flag.Arg(2)
fromVersionUint := parseUint32(fromVersion)
toVersionUint := parseUint32(toVersion)
if fromVersionUint >= toVersionUint {
log.Fatalf("couldn't create pack: FROM_VERSION (%d) must be smaller than TO_VERSION (%d)", fromVersionUint, toVersionUint)
}
chrootDir := ""
if *useChroot {
chrootDir = filepath.Join(stateDir, "image")
if _, err := os.Stat(chrootDir); err != nil {
log.Fatalf("couldn't access the full chroot: %s", err)
}
}
bundles := make(map[string]*swupd.BundleToPack)
if *allBundles {
toDir := filepath.Join(stateDir, "www", toVersion)
toMoM, err := swupd.ParseManifestFile(filepath.Join(toDir, "Manifest.MoM"))
if err != nil {
log.Fatalf("couldn't read MoM of TO_VERSION (%s): %s", toVersion, err)
}
var fromMoM *swupd.Manifest
if fromVersionUint > 0 {
fromDir := filepath.Join(stateDir, "www", fromVersion)
fromMoM, err = swupd.ParseManifestFile(filepath.Join(fromDir, "Manifest.MoM"))
if err != nil {
log.Fatalf("couldn't read MoM of FROM_VERSION (%s): %s", fromVersion, err)
}
}
bundles, err = swupd.FindBundlesToPack(fromMoM, toMoM)
if err != nil {
log.Fatalf("couldn't find the bundles to pack: %s", err)
}
} else {
// If we are handling a single bundle, its name is taken directly from the command line.
name := flag.Arg(3)
if name == "full" || name == "MoM" || name == "" {
log.Fatalf("invalid bundle name %q", name)
}
bundle := &swupd.BundleToPack{
Name: name,
FromVersion: fromVersionUint,
ToVersion: toVersionUint,
}
bundles["name"] = bundle
}
// TODO: Use goroutines.
for _, b := range bundles {
// Unless we are forcing, skip the packs already on disk.
if !*force {
_, err := os.Lstat(filepath.Join(stateDir, "www", fmt.Sprint(b.ToVersion), swupd.GetPackFilename(b.Name, b.FromVersion)))
if err == nil {
fmt.Printf("Pack already exists for %s from %d to %d\n", b.Name, b.FromVersion, b.ToVersion)
continue
}
if !os.IsNotExist(err) {
log.Fatal(err)
}
}
fmt.Printf("Packing %s from %d to %d...\n", b.Name, b.FromVersion, b.ToVersion)
info, err := swupd.CreatePack(b.Name, b.FromVersion, b.ToVersion, filepath.Join(stateDir, "www"), chrootDir)
if err != nil {
log.Fatal(err)
}
if len(info.Warnings) > 0 {
log.Println("Warnings during pack:")
for _, w := range info.Warnings {
log.Printf(" %s\n", w)
}
log.Println()
}
fmt.Printf(" Fullfiles in pack: %d\n", info.FullfileCount)
fmt.Printf(" Deltas in pack: %d\n", info.DeltaCount)
}
}
func parseUint32(s string) uint32 {
parsed, err := strconv.ParseUint(s, 10, 32)
if err != nil {
log.Fatalf("error parsing value %q: %s", s, err)
}
return uint32(parsed)
}