summaryrefslogtreecommitdiff
path: root/eclass/sab-patches.eclass
blob: 40e89911d784824458db839bfd23180fdb4a737d (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
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
# Copyright 2014 Sabayon
# Distributed under the terms of the GNU General Public License v2
# $Header: $

# @ECLASS: sab-patches.eclass
# @MAINTAINER:
# slawomir.nizio@sabayon.org
# @AUTHOR:
# Sławomir Nizio <slawomir.nizio@sabayon.org>
# @BLURB: eclass that makes it easier to apply patches from multiple packages
# @DESCRIPTION:
# Makes it easy to apply patches stored in a remote location
# with the intention to make the task easier for Sabayon split ebuilds.
# (Plain patches kept in a VCS are very nice, but in the case of split
# ebuilds, duplicating the patches is not effective.)
# Patches are not added to SRC_URI by default, because it makes ebuilds
# use "SRC_URI+=..." which makes them more diverged from the original
# one than necessary.
# The eclass does not define any phase function.

# @ECLASS-VARIABLE: SAB_PATCHES_SRC
# @DEFAULT_UNSET
# @DESCRIPTION:
# Array that contains URIs of patches to be added to SRC_URI. Mandatory!

# @ECLASS-VARIABLE: SAB_PATCHES_SKIP
# @DESCRIPTION:
# Array that contains patterns of patch names to be skipped.
# It does not need to be a global variable.

inherit eutils

if [[ ${#SAB_PATCHES_SRC[@]} -eq 0 ]]; then
	die "SAB_PATCHES_SRC is not set"
fi

# @FUNCTION: sab-patches_update_SRC_URI
# @DESCRIPTION:
# Appends patches entries to SRC_URI. If it is not done, an error will
# occur later on.
sab-patches_update_SRC_URI() {
	local p
	for p in "${SAB_PATCHES_SRC[@]}"; do
		SRC_URI+=${SRC_URI:+ }${p}
	done
}

# @FUNCTION: sab-patches_apply_all
# @DESCRIPTION:
# Applies patches specified using SAB_PATCHES_SRC, skipping patches
# with names matched in SAB_PATCHES_SKIP.
# Two possible cases are supported.
# 1. A patch path which is a tarball (assumed file name: *.tar*).
# Such a tarball must unpack to ${WORKDIR}/<tarball name without *.tar*>
# and must contain a file 'order,' which is used to determine order
# of patches to apply.
# 2. A patch which is not a tarball, which will be simply applied (if
# it is not skipped).
sab-patches_apply_all() {
	local p
	for p in "${SAB_PATCHES_SRC[@]}"; do
		if [[ ${p} = *.tar* ]]; then
			local dir=${p##*/}
			dir=${dir%.tar*}
			_sab-patches_apply_from_dir "${WORKDIR}/${dir}"
		else
			local name=${p##*/}
			_sab-patches_apply_nonskipped "${DISTDIR}" "${name}"
		fi
	done
}

# @FUNCTION: sab-patches_apply
# @DESCRIPTION:
# Apply selected patches. Arguments are the directory containing
# the patch, followed by one or more patch names.
sab-patches_apply() {
	[[ $# -lt 2 ]] && die "sab-patches_apply: missing arguments"
	local dir=$1
	shift
	local patch
	for patch; do
		epatch "${dir}/${patch}"
	done
}

# @FUNCTION: sab-patches_unpack
# @DESCRIPTION:
# Unpack every file provided in SAB_PATCHES_SRC.
sab-patches_unpack() {
	local p
	pushd "${WORKDIR}" > /dev/null || die

	for p in "${SAB_PATCHES_SRC[@]}"; do
		local name=${p##*/}
		unpack "${name}"
	done

	popd > /dev/null || die
}

# @FUNCTION: _sab-patches_apply_nonskipped
# @INTERNAL
# @DESCRIPTION:
# Apply selected patches - only those which should not be skipped.
# Arguments are the directory containing the patch, followed by
# one or more patch names.
# This function is not intended to be used by ebuilds because there
# is a better way: use sab-patches_apply and skip the unwanted ones.
_sab-patches_apply_nonskipped() {
	if [[ $# -lt 2 ]]; then
		die "_sab-patches_apply_nonskipped: missing arguments"
	fi

	local dir=$1
	shift

	local patch
	for patch; do
		if [[ ${patch} = */* ]]; then
			die "_sab-patches_apply_nonskipped: '${patch}' contains slashes"
		fi

		if _sab-patches_is_skipped "${patch}"; then
			einfo "(skipping ${patch})"
		else
			epatch "${dir}/${patch}"
		fi
	done
}

# @FUNCTION: _sab-patches_apply_from_dir
# @INTERNAL
# @DESCRIPTION:
# Apply all patches from a directory in order. Obeys SAB_PATCHES_SKIP.
_sab-patches_apply_from_dir() {
	local dir=$1
	local order_file=${dir}/order
	if [[ ! -r ${order_file} ]] || [[ ! -f ${order_file} ]]; then
		die "Problems with '${order_file}'... (Does it exist?)"
	fi

	local patch
	while read patch; do
		local patch_path=${dir}/${patch}
		if \
			[[ -z ${patch} ]]    || \
			[[ ${patch} = *\ * ]] || \
			[[ ${patch} = */* ]] || \
			[[ ! -f ${patch_path} ]]; then
			die "Problems with the patch '${patch}', see ${order_file}."
		fi

		_sab-patches_apply_nonskipped "${dir}" "${patch}"
	done < "${order_file}"

	[[ $? -ne 0 ]] && die "_sab-patches_apply_from_dir: loop failed"
}

# @FUNCTION: _sab-patches_is_skipped
# @INTERNAL
# @DESCRIPTION:
# Returns success if the patch should be skipped. O(n). :)
_sab-patches_is_skipped() {
	local arg=$1
	local p
	for p in "${SAB_PATCHES_SKIP[@]}"; do
		[[ ${arg} = ${p} ]] && return 0
	done
	return 1
}