aboutsummaryrefslogtreecommitdiff
path: root/lib/utils
blob: 5281d196c11865facb475f11fbb20231b4364c28 (plain)
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
# vim: ft=sh

die() {
	echo "$@" >&2
	kill $$
}

# Returns name of this module
module_id() {
	$(basename "$0")
}

# Status file for this module
MC_STATUS_FILE="$MC_STATUS_DIR/$(module_id)"

# Return hash of given file from status file
# First argument have to be a path to output file
installed_hash() {
	awk -F '\t' -v regex="^$1$" '/$2 ~ regex { print $1 }' "$MC_STATUS_FILE"
}

# Hash of currently installed file
# Access remote resource
# It connects to remote server and requests resource for given plugin.
# It expects only one argument and that is resource identifier.
remote_source() {
	local res="$1"
	local mod_id="$(module_id)"
	if [ -n "$MC_LOCAL_DIR" ]; then
		"$MC_LOCAL_DIR/request.sh" "$mod_id:$res"
	else
		ssh -i ~/.ssh/multiconfig multiconfig@cynerd.cz -- "$mod_id:$res"
	fi
}

# Defined and create QUEUE file for this instance
MC_QUEUE_FILE="$(mktemp multiconfig-$(module_id).queue.XXXXXX)"
touch "$MC_QUEUE_FILE"

# Variable signaling if file was updated or not
change=false

# Install given file
# First argument has to be a identifier string for remote script
# Second argument has to be an output file (absolute path).
inst() {
	local src="$1"
	local out="$2"
	[ -f "$MC_QUEUE_FILE" ] || die "inst can be called only before apply call!"
	grep -q "\t$out$" || die "inst can be called on one output only once!"
	# TODO verify that this output is not already in queue
	local tmp="$(mktemp multiconfig.XXXXXXXXXX)"
	remote_source "$src" > "$tmp"
	local refhash="$(installed_hash "$out")"
	if [ -n "$refhash" ]; then
		change=false
		if [ -f "$out" ]; then
			local cursha="$(sha256 "$out")"
			if [ "$cursha" != "$(sha256 "$tmp")" ]; then
				echo "Updating file ($src): $out"
				[ "$cursha" = "$refhash" ] || echo "File was edited manually! $out"
				echo "$tmp	$out" >> "$MC_QUEUE_FILE"
				change=true
			fi
		else
			echo "Output is not a file! $out"
			echo "$tmp	$out" >> "$MC_QUEUE_FILE"
			change=true
		fi
	else
		echo "New file ($src): $out"
		echo "$tmp	$out" >> "$MC_QUEUE_FILE"
		change=true
	fi
}

# Apply all queued changes and cleanup
apply() {
	local new="$MC_STATUS_FILE.new"
	echo -n > "$new"
	while IFS=\t read src out; do
		if [ -e "$out" ]; then
			local trash="$MC_TRASH_DIR/$out.$(date +%y%m%d%H%M%S)"
			if [ -f "$out" ]; then
				if [ "$(installed_hash "$out")" != "$(sha256 "$out")" ]; then
					echo "File was manually changed: $out -> $trash"
					cp "$out" "$trash"
				fi
			else
				echo "Path exists but is not a file: $out -> $trash"
				mv "$out" "$trash"
			fi
		fi
		echo "Updating: $out"
		mv "$src" "$out"
		sha256 "$out" >> "$new"
	done < "$MC_QUEUE_FILE"
	rm "$MC_QUEUE_FILE"
	mv "$new" "$MC_STATUS_FILE"
	change=
}

# TODO somehow add support for installing directories. Most probably by having
# remote script returning list of files in directory and then calling inst on
# them.

# Returns string informing you of distribution type but only if given distribution
# is supported. If ditribution is not supported then it returns "unknown".
distribution() {
	if [ -f /etc/gentoo-release ]; then
		echo "gentoo"
	elif [ -f /etc/alpine-release ]; then
		echo "alpine"
	elif [ -f /etc/openwrt_version ]; then
		echo "openwrt"
	else
		echo "unknown"
	fi
}