~dricottone/simple-builder

ref: 5efee8c6bb548138cfb63a24ed7c7747d366486a simple-builder/apk.go -rw-r--r-- 3.6 KiB
5efee8c6Dominic Ricottone Update 6 months ago
                                                                                
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
package main

import (
	"bufio"
	"fmt"
	"os"
	"path"
	"regexp"
	"strings"
)

var (
	pattern_pkgver = regexp.MustCompile(`^pkgver=(.*)$`)
	pattern_pkgrel = regexp.MustCompile(`^pkgrel=(.*)$`)
	pattern_depends = regexp.MustCompile(`^depends="(.*)"$`)
	pattern_apkname = regexp.MustCompile(`^([A-Za-z0-9._-]+)-([0-9]+\.[0-9]+(\.[0-9]+)?(\.[0-9]+)?-r[0-9]+)\.apk$`)
)

// Scan a directory for an APKBUILD file.
func find_apkbuild(pkg *Package, directory string) error {
	members, err := os.ReadDir(directory)
	if (err != nil) {
		return err
	}

	for _, member := range members {
		if (member.Name() == "APKBUILD") {
			err = parse_apkbuild(pkg, path.Join(directory, member.Name()))
			if (err != nil) {
				return err
			}
			return nil
		}
	}

	return fmt.Errorf("No APKBUILD in %s", pkg.Name)
}

// Parse an APKBUILD file. Given an existing Package, add core information
// (Version, Dependencies) as it is identified.
func parse_apkbuild(pkg *Package, filename string) error {
	pkgver := ""
	pkgrel := ""
	depends := []string{}
	inside_depends := false

	file, err := os.Open(filename)
	if (err != nil) {
		return err
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()

		match := pattern_pkgver.FindStringSubmatch(line)
		if (match != nil) {
			pkgver = match[1]
		}
		match = pattern_pkgrel.FindStringSubmatch(line)
		if (match != nil) {
			pkgrel = match[1]
		}
		
		if (inside_depends == true) {
			if (line == "\"") {
				inside_depends = false
			} else {
				depends = append(depends, parse_list(line)...)
			}
		} else if (line == "depends=\"") {
			inside_depends = true
		}

		match = pattern_depends.FindStringSubmatch(line)
		if (match != nil) {
			depends = append(depends, parse_list(match[1])...)
		}
	}

	err = scanner.Err()
	if (err != nil) {
		return err
	}

	if (pkgver == "") || (pkgrel == "") {
		return fmt.Errorf("APKBUILD is incomplete in %s", pkg.Name)
	}
	pkg.Version = pkgver + "-r" + pkgrel

	if (len(depends) != 0) {
		pkg.Dependencies = depends
	}

	return nil
}

// Scan a filename for an apk file. If one is identified, create a Package to
// represent it with all available information (Name and Version).
func find_apk(filename string) (Package, error) {
	match := pattern_apkname.FindStringSubmatch(filename)
	if (match != nil) {
		return new_package_with_version(match[1], match[2]), nil
	}
	return Package{}, fmt.Errorf("Could not identify apk in %s", filename)
}

// Construct the local directory expected to be built into.
func expected_apkdir(local_dir, arch string) string {
	if (arch == "amd64") {
		return path.Join(local_dir, "x86_64")
	} else if (arch == "arm64") {
		return path.Join(local_dir, "aarch64")
	}
	return local_dir
}

// Construct the apk filename expected to correspond to a Package.
func expected_apk(pkg Package) string {
	return fmt.Sprintf("%s-%s.apk", pkg.Name, pkg.Version)
}

// Reconstruct the relevant parts of the APKBUILD files that were parsed.
func dump_apkbuilds(packages []Package, debug_prefix string) {
	total := len(packages)
	for i, p := range packages {
		version := strings.SplitN(p.Version, "-r", 2)
		fmt.Printf("DEBUG-APK:[%d/%d] %s\n", i + 1, total, p.Name)
		fmt.Printf("DEBUG-APK:pkgver=%s\n", version[0])
		fmt.Printf("DEBUG-APK:pkgrel=%s\n", version[1])
		has_dependencies := (0 < len(p.Dependencies))
		print_if(has_dependencies, "DEBUG-APK:depends=\"")
		for _, d := range p.Dependencies {
			fmt.Printf("DEBUG-APK:\t%s\n", d)
		}
		print_if(has_dependencies, "DEBUG-APK:\"")
		fmt.Println("DEBUG-APK:")
	}
}

// Parse a string as a whitespace-delimited list.
func parse_list(list string) []string {
	return strings.Split(strings.TrimSpace(list), " ")
}