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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
|
#!/bin/sh
#
# This script has been modified by kosmikus and is based on
# python-updater by liquidx.
#
# It tries to update any package that provides a ghc library.
# This script can be run as many times as you like. It will log the
# results in /var/log/ghc-updater.log
#
# NEW_GHC_VER = new ghc version we are upgrading to
# PKGS_EXCEPTIONS = packages that should NOT be re-emerged for any reason
# PKGS_MANUAL = packages that should be re-emerged even if they don't
# fit the criteria
#
# Runtime Variables:
#
# PKGS_TO_REMERGE = list of packages we deem to need re-emerging
# PKGS_OK = list of packages that should be merged without any problems
# PKGS_MISSING = list of packages that are installed, but cannot be merged
# because they have been pruned from portage
# PKGS_MASKED = list of packages that are installed, but masked.
#
shopt -s nullglob
# fix the PATH to include the dirs where portage installs ghc
PATH="/usr/bin:/opt/ghc/bin:${PATH}"
NEW_GHC_VER=$(ghc --version | sed 's:^.*version ::')
NEW_GHC_LIBDIR=$(ghc --print-libdir)
PKGS_EXCEPTIONS="dev-lang/ghc dev-lang/ghc-bin"
PKGS_MANUAL=""
LOGFILE="/var/log/ghc-updater.log"
# portage variables
PKG_DBDIR=/var/db/pkg
# moved the portageq checks into a function to make command
# line parsing immediate
setup_portdir() {
PORTDIR=`portageq portdir`
PORTDIR_OVERLAYS=`portageq portdir_overlay`
}
PRETEND=0
PKGS_TO_REMERGE=""
PKGS_COUNT_REMERGE=0
PORTAGE_PYTHON="/usr/bin/python"
usage() {
echo "usage: ghc-updater [options]"
echo " -h, -?, --help help"
echo " -p, --pretend pretend (don't do anything)"
}
#
#
# Command Line Parsing
#
#
while [ -n "$1" ]; do
case "$1" in
-h | -\? | --help)
usage
exit 0
;;
-p | --pretend)
PRETEND=1
;;
*)
usage
echo "unrecognised option: $1"
;;
esac
shift
done
# load the gentoo-style info macros, but hack to get around
# it thinking this is an rc script
EBUILD="1"
source /sbin/functions.sh
# misc helper functions
eloginfo() {
einfo $*
DATESTRING=`date +"%Y/%m/%d %H:%M:%S"`
(echo "${DATESTRING} - ${*}" >> ${LOGFILE}) 2>/dev/null
}
elogecho() {
echo -n " "
echo $*
DATESTRING=`date +"%Y/%m/%d %H:%M:%S"`
(echo "${DATESTRING} - ${*}" >> ${LOGFILE}) 2>/dev/null
}
elogerr() {
eerror $*
DATESTRING=`date +"%Y/%m/%d %H:%M:%S"`
(echo "${DATESTRING} ! ${*}" >> ${LOGFILE}) 2>/dev/null
}
elog() {
DATESTRING=`date +"%Y/%m/%d %H:%M:%S"`
(echo "${DATESTRING} - ${*}" >> ${LOGFILE}) 2>/dev/null
}
#
# Sanity check
#
setup_portdir
find_in_portdir() {
local f
for f in ${PORTDIR} ${PORTDIR_OVERLAYS}; do
if [[ -f "${f}/${1}" ]]; then
echo "${f}/${1}"
return 0
fi
done
return 1
}
if [ -z "${PORTDIR}" ]; then
eerror "Unable to proceed. Can not find PORTDIR. Make sure the command:"
eerror " "
eerror " portageq portdir"
eerror " "
eerror "returns a value. If it doesn't, make sure you have updated to"
eerror "latest portage version."
eerror " "
eerror "Report bugs to http://bugs.gentoo.org/"
exit 1
fi
#
#
# Find all packages that have installed something in
# directories of the form
# /usr/lib/ghc-<version>
# or similar.
#
# /usr/lib/ghc-bin-<version>
# is included because an old ghc-bin ebuild was buggy and
# installed to a wrong dir.
#
OLD_PACKAGES_DIR=""
# Exclude new library dir and lib symlinks:
for d in /{usr,opt/ghc}/lib{,64}/ghc{,-bin}-*; do
[[ "${d}" == ${NEW_GHC_LIBDIR} ]] || [[ -L ${d%/*} ]] || OLD_PACKAGES_DIR="${OLD_PACKAGES_DIR}${d} "
done
eloginfo "Starting GHC Updater to $(which ghc), version ${NEW_GHC_VER} :"
eloginfo "Searching for packages with files in the directories:"
eloginfo "${OLD_PACKAGES_DIR}"
# iterate thru all the installed package's contents
for content in `find ${PKG_DBDIR} -name CONTENTS`; do
# extract the category, package name and package version
CATPKGVER=$(echo ${content} | sed "s:${PKG_DBDIR}/\(.*\)/CONTENTS:\1:")
# exclude packages that are an exception, like portage and python itself.
exception=0
for exp in ${PKGS_EXCEPTIONS}; do
if [ -n "$(echo ${CATPKGVER} | grep ${exp})" ]; then
exception=1
break;
fi
done
if [ ${exception} = 1 ]; then
continue;
fi
for d in ${OLD_PACKAGES_DIR}; do
if fgrep "${d}/" ${content} > /dev/null; then
PKGS_TO_REMERGE="${PKGS_TO_REMERGE} ${CATPKGVER}"
elogecho "${CATPKGVER} has files in ${d}"
fi
done
done
# now we have to do each emerge seperately because if an installed version
# does not have the corresponding ebuild in portage, then it will bail.
eloginfo "Calculating Upgrade Package List .."
PKGS_OK=""
PKGS_MASKED=""
PKGS_BLOCKED=""
PKGS_MISSING=""
MASKED_STRING="been masked"
BLOCKED_STRING="is blocking"
MISSING_STRING='there are no ebuilds to satisfy'
for pkg in ${PKGS_TO_REMERGE}; do
emerge_output="$(emerge -p '>='$pkg 2>&1)"
if $(echo "${emerge_output}" | grep "${MASKED_STRING}" > /dev/null); then
PKGS_MASKED="${PKGS_MASKED} $pkg"
elogecho ">=$pkg is masked"
elif $(echo "${emerge_output}" | grep "${BLOCKED_STRING}" > /dev/null); then
PKGS_BLOCKED="${PKGS_BLOCKED} $pkg"
elogecho ">=$pkg is blocked"
elif $(echo "${emerge_output}" | grep "${MISSING_STRING}" > /dev/null); then
PKGS_MISSING="${PKGS_MISSING} $pkg"
elogecho ">=$pkg is missing from portage"
else
PKGS_OK="${PKGS_OK} $pkg"
PKGS_COUNT_REMERGE=$((PKGS_COUNT_REMERGE + 1))
fi
done
#
# Use my super dumb package reordering algorithm that works most of the time
#
eloginfo "Re-ordering packages to merge .."
DEPSORT=$(find_in_portdir "dev-lang/ghc/files/depsort.py")
if [[ -z ${DEPSORT} ]]; then
eerror "Fatal error: File dev-lang/ghc/files/depsort.py in portage tree."
exit 1
fi
PKGS_OK_SORTED="$(${PORTAGE_PYTHON} ${DEPSORT} ${PKGS_OK} | xargs)"
if [[ -n ${PRETEND} ]]; then
eloginfo "These are the packages that would be merged, in order:"
else
eloginfo "Preparing to merge these packages in this order:"
fi
for pkg in $PKGS_OK_SORTED; do
elogecho ">=$pkg"
done
# we emerge each package seperately to ensure we know exactly which ones might
# cause an error, and then report it at the end
COUNT=1
PKGS_FAILED=""
if [ "${PRETEND}" != "1" ]; then
for pkg in ${PKGS_OK_SORTED}; do
eloginfo "Starting to merge ($COUNT/$PKGS_COUNT_REMERGE) $pkg .."
if ! emerge --oneshot --nodeps '>='$pkg; then
PKGS_FAILED="${PKGS_FAILED} $pkg"
elogerr "Failed merging $pkg ($COUNT/$PKGS_COUNT_REMERGE)!"
fi
COUNT=$((COUNT+1))
done
fi
# final output stuff
OUTPUT_PKGS_MASKED=""
for pkg in ${PKGS_MASKED}; do OUTPUT_PKGS_MASKED="${OUTPUT_PKGS_MASKED} '>='$pkg"; done
OUTPUT_PKGS_BLOCKED=""
for pkg in ${PKGS_BLOCKED}; do OUTPUT_PKGS_BLOCKED="${OUTPUT_PKGS_BLOCKED} $pkg"; done
OUTPUT_PKGS_MISSING=""
for pkg in ${PKGS_MISSING}; do OUTPUT_PKGS_MISSING="${OUTPUT_PKGS_MISSING} $pkg"; done
OUTPUT_PKGS_FAILED=""
for pkg in ${PKGS_FAILED}; do OUTPUT_PKGS_FAILED="${OUTPUT_PKGS_FAILED} '>='$pkg"; done
if [ -n "${PKGS_FAILED}" -o -n "${PKGS_MISSING}" -o -n "${PKGS_MASKED}" ]; then
echo
ewarn "************************************************************"
ewarn "* Packages that still need to be manually emerged : *"
ewarn "************************************************************"
if [ -n "${OUTPUT_PKGS_MASKED}" ]; then
echo
ewarn " Masked Packages:"
ewarn " ----------------"
ewarn " Unmask the following packages (at your own risk) and "
ewarn " emerge them using this command after removing the '-p'"
ewarn " parameter."
echo
ewarn " emerge -p ${OUTPUT_PKGS_MASKED}"
echo
fi
if [ -n "${OUTPUT_PKGS_BLOCKED}" ]; then
echo
ewarn " Blocked Packages:"
ewarn " -----------------"
ewarn " These packages are currently blocked; they might not yet"
ewarn " be compatible with the current ghc. You can run ghc-updater"
ewarn " again at a later time."
echo
for x in ${OUTPUT_PKGS_BLOCKED}; do
echo " ${x}"
done
fi
if [ -n "${OUTPUT_PKGS_MISSING}" ]; then
echo
ewarn " Missing Packages:"
ewarn " -----------------"
ewarn " These packages cannot be updated because they do not exist"
ewarn " in portage anymore."
echo
for x in ${OUTPUT_PKGS_MISSING}; do
echo " ${x}"
done
fi
if [ -n "${OUTPUT_PKGS_FAILED}" ]; then
echo
ewarn " Failed Packages:"
ewarn " ----------------"
ewarn " These packages have failed and need to be re-emerged again."
ewarn " Alternatively, try re-running this script again to see if it"
ewarn " can be fixed."
echo
ewarn " emerge -p ${OUTPUT_PKGS_FAILED}"
echo
fi
elog "GHC update completed with errors."
elog "Masked Packages:"
for x in ${PKGS_MASKED}; do
elog $x
done
elog "Missing Packages:"
for x in ${PKGS_MISSING}; do
elog $x
done
elog "Failed Packages:"
for x in ${PKGS_FAILED}; do
elog $x
done
elog "Update script completed."
else
eloginfo "GHC update completed successfully."
fi
|