Gentoo Archives: gentoo-commits

From: Patrick McLean <chutzpah@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: sys-cluster/ceph/, sys-cluster/ceph/files/
Date: Tue, 08 Jan 2019 00:13:35
Message-Id: 1546906397.030c87d27bca481566a44e7f8a891da41a46fcc6.chutzpah@gentoo
1 commit: 030c87d27bca481566a44e7f8a891da41a46fcc6
2 Author: Patrick McLean <patrick.mclean <AT> sony <DOT> com>
3 AuthorDate: Tue Jan 8 00:12:48 2019 +0000
4 Commit: Patrick McLean <chutzpah <AT> gentoo <DOT> org>
5 CommitDate: Tue Jan 8 00:13:17 2019 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=030c87d2
7
8 sys-cluster/ceph: Version bump to 13.2.4
9
10 Also update init script to resolve bug #673554
11
12 Bug: https://bugs.gentoo.org/673554
13 Copyright: Sony Interactive Entertainment Inc.
14 Package-Manager: Portage-2.3.54, Repoman-2.3.12
15 Signed-off-by: Patrick McLean <chutzpah <AT> gentoo.org>
16
17 sys-cluster/ceph/Manifest | 1 +
18 sys-cluster/ceph/ceph-13.2.4.ebuild | 335 ++++++++++++++++++++++++++++++++++
19 sys-cluster/ceph/files/ceph.initd-r11 | 115 ++++++++++++
20 3 files changed, 451 insertions(+)
21
22 diff --git a/sys-cluster/ceph/Manifest b/sys-cluster/ceph/Manifest
23 index 23aa8981d97..2e581c4d696 100644
24 --- a/sys-cluster/ceph/Manifest
25 +++ b/sys-cluster/ceph/Manifest
26 @@ -8,3 +8,4 @@ DIST ceph-13.2.1-frontend-node-modules.tar.xz 44352460 BLAKE2B 0a0099e60f0b36d48
27 DIST ceph-13.2.1.tar.gz 90786830 BLAKE2B e0884a039ff0e8a1705d8f31f4dcf4cd8ab8989d7c2fa703417038ff9a6cf7b0fbca09abceb901970fbb2dd9a1dc87c2500fec38a2bfca86a9a6dcaab15be991 SHA512 411218ea6037bdf9425a741720ea89876e893e64fbfa518c9584ba581f805fde2c82b13ed47313279665e5d20f36223fc8d5c27055b580c72b22c2004e4da81b
28 DIST ceph-13.2.2-frontend-node-modules.tar.xz 45100632 BLAKE2B c3929a6c5e6ec3da5ff60967ae40b99377b2186f31e64af571d9be14889d90bc48b570489aea300ead8e99afc0e62db4438cf343686757a39d84889e772c7fa9 SHA512 93eabc2010c0977c2980c739e131d231a809e375c42120e81effc6cecdeaf0e50b4f8c88286993ef60f1ffaede94f637475104e09fd7af58a289350bd670bf2f
29 DIST ceph-13.2.2.tar.gz 90840817 BLAKE2B db5933f358a1ae6888030bca7522e20545a2e107055dca44b371e295537c854568682fa558d3f90193e0dfe618947918ce21816b5e20795fff8a14bc837216bb SHA512 37c4845ae52550428c7f1e0d77d9d671ea1d6f5cad5bce0713dce97b54f3abe7346daa2cbd44b76638fb74fe7bdc4797033a4bf808253cfc8bec0fa495ec7e03
30 +DIST ceph-13.2.4.tar.gz 90910119 BLAKE2B eb395f435552d91789869bd92fee2a8b2fef155205f13b118bd01be4ff78a8e1dde682425a24311822bb819ec8cf41a9d45245ffa3cb7a921d3269f6658bf920 SHA512 5055979067234ad7fd2774007d524ef4643d968bf7ce42fc8c3f8e469fd84cbd7afc163cd6ddda53584bd5677fdea2fecf8194a378d49724504f639b9f688ff7
31
32 diff --git a/sys-cluster/ceph/ceph-13.2.4.ebuild b/sys-cluster/ceph/ceph-13.2.4.ebuild
33 new file mode 100644
34 index 00000000000..58a11edc773
35 --- /dev/null
36 +++ b/sys-cluster/ceph/ceph-13.2.4.ebuild
37 @@ -0,0 +1,335 @@
38 +# Copyright 1999-2019 Gentoo Authors
39 +# Distributed under the terms of the GNU General Public License v2
40 +
41 +EAPI=6
42 +PYTHON_COMPAT=( python{2_7,3_{4,5,6}} )
43 +DISTUTILS_OPTIONAL=1
44 +
45 +inherit check-reqs bash-completion-r1 cmake-utils distutils-r1 flag-o-matic \
46 + multiprocessing python-r1 udev user readme.gentoo-r1 toolchain-funcs \
47 + systemd
48 +
49 +if [[ ${PV} == *9999* ]]; then
50 + inherit git-r3
51 + EGIT_REPO_URI="https://github.com/ceph/ceph.git"
52 + SRC_URI=""
53 +else
54 + SRC_URI="https://download.ceph.com/tarballs/${P}.tar.gz"
55 + KEYWORDS="~amd64 ~x86"
56 +fi
57 +
58 +DESCRIPTION="Ceph distributed filesystem"
59 +HOMEPAGE="https://ceph.com/"
60 +
61 +LICENSE="LGPL-2.1 CC-BY-SA-3.0 GPL-2 BSD Boost-1.0 MIT"
62 +SLOT="0"
63 +
64 +CPU_FLAGS_X86=(sse{,2,3,4_1,4_2} ssse3)
65 +
66 +IUSE="babeltrace cephfs dpdk fuse jemalloc ldap lttng +mgr"
67 +IUSE+=" +radosgw +ssl static-libs +system-boost systemd +tcmalloc test"
68 +IUSE+=" xfs zfs"
69 +IUSE+=" $(printf "cpu_flags_x86_%s\n" ${CPU_FLAGS_X86[@]})"
70 +
71 +# unbundling code commented out pending bugs 584056 and 584058
72 +#>=dev-libs/jerasure-2.0.0-r1
73 +#>=dev-libs/gf-complete-2.0.0
74 +COMMON_DEPEND="
75 + virtual/libudev:=
76 + app-arch/bzip2:=[static-libs?]
77 + app-arch/lz4:=[static-libs?]
78 + app-arch/snappy:=[static-libs?]
79 + app-arch/zstd:=[static-libs?]
80 + app-misc/jq:=[static-libs?]
81 + dev-libs/crypto++:=[static-libs?]
82 + dev-libs/leveldb:=[snappy,static-libs?,tcmalloc?]
83 + dev-libs/libaio:=[static-libs?]
84 + dev-libs/libxml2:=[static-libs?]
85 + dev-libs/nss:=
86 + sys-auth/oath-toolkit:=
87 + sys-apps/keyutils:=[static-libs?]
88 + sys-apps/util-linux:=[static-libs?]
89 + sys-libs/zlib:=[static-libs?]
90 + babeltrace? ( dev-util/babeltrace )
91 + ldap? ( net-nds/openldap:=[static-libs?] )
92 + lttng? ( dev-util/lttng-ust:= )
93 + fuse? ( sys-fs/fuse:0=[static-libs?] )
94 + ssl? ( dev-libs/openssl:=[static-libs?] )
95 + xfs? ( sys-fs/xfsprogs:=[static-libs?] )
96 + zfs? ( sys-fs/zfs:=[static-libs?] )
97 + mgr? (
98 + <net-libs/nodejs-9.0
99 + >net-libs/nodejs-8.10
100 + )
101 + radosgw? (
102 + dev-libs/expat:=[static-libs?]
103 + dev-libs/openssl:=[static-libs?]
104 + net-misc/curl:=[curl_ssl_openssl,static-libs?]
105 + )
106 + system-boost? (
107 + >=dev-libs/boost-1.67:=[threads,context,python,static-libs?,${PYTHON_USEDEP}]
108 + )
109 + jemalloc? ( dev-libs/jemalloc:=[static-libs?] )
110 + !jemalloc? ( >=dev-util/google-perftools-2.4:=[static-libs?] )
111 + ${PYTHON_DEPS}
112 + "
113 +DEPEND="${COMMON_DEPEND}
114 + amd64? ( dev-lang/yasm )
115 + x86? ( dev-lang/yasm )
116 + app-arch/cpio
117 + dev-python/cython[${PYTHON_USEDEP}]
118 + dev-python/sphinx
119 + dev-util/cunit
120 + dev-util/gperf
121 + dev-util/valgrind
122 + sys-apps/which
123 + sys-devel/bc
124 + virtual/pkgconfig
125 + test? (
126 + dev-python/coverage[${PYTHON_USEDEP}]
127 + dev-python/tox[${PYTHON_USEDEP}]
128 + dev-python/virtualenv[${PYTHON_USEDEP}]
129 + sys-apps/grep[pcre]
130 + sys-fs/btrfs-progs
131 + )"
132 +RDEPEND="${COMMON_DEPEND}
133 + net-misc/socat
134 + sys-apps/gptfdisk
135 + sys-block/parted
136 + sys-fs/cryptsetup
137 + sys-fs/lvm2
138 + !<sys-apps/openrc-0.26.3
139 + dev-python/bcrypt[${PYTHON_USEDEP}]
140 + dev-python/cherrypy[${PYTHON_USEDEP}]
141 + dev-python/flask[${PYTHON_USEDEP}]
142 + dev-python/jinja[${PYTHON_USEDEP}]
143 + dev-python/pecan[${PYTHON_USEDEP}]
144 + dev-python/prettytable[${PYTHON_USEDEP}]
145 + dev-python/pyopenssl[${PYTHON_USEDEP}]
146 + dev-python/requests[${PYTHON_USEDEP}]
147 + dev-python/werkzeug[${PYTHON_USEDEP}]
148 + "
149 +REQUIRED_USE="
150 + ${PYTHON_REQUIRED_USE}
151 + || ( $(python_gen_useflags 'python3*') )
152 + ?? ( jemalloc tcmalloc )
153 + "
154 +
155 +# the tests need root access
156 +RESTRICT="test? ( userpriv )"
157 +
158 +# distribution tarball does not include everything needed for tests
159 +RESTRICT+=" test"
160 +
161 +# false positives unless all USE flags are on
162 +CMAKE_WARN_UNUSED_CLI="no"
163 +
164 +STRIP_MASK="/usr/lib*/rados-classes/*"
165 +
166 +UNBUNDLE_LIBS=(
167 + src/erasure-code/jerasure/jerasure
168 + src/erasure-code/jerasure/gf-complete
169 +)
170 +
171 +PATCHES=(
172 + "${FILESDIR}/ceph-12.2.0-use-provided-cpu-flag-values.patch"
173 + "${FILESDIR}/ceph-12.2.0-cflags.patch"
174 + "${FILESDIR}/ceph-12.2.4-boost-build-none-options.patch"
175 + "${FILESDIR}/ceph-13.2.0-cflags.patch"
176 + "${FILESDIR}/ceph-12.2.4-rocksdb-cflags.patch"
177 + "${FILESDIR}/ceph-13.2.0-mgr-python-version.patch"
178 + "${FILESDIR}/ceph-13.2.0-no-virtualenvs.patch"
179 + "${FILESDIR}/ceph-13.2.2-dont-install-sysvinit-script.patch"
180 +)
181 +
182 +check-reqs_export_vars() {
183 + if use amd64; then
184 + CHECKREQS_DISK_BUILD="12G"
185 + CHECKREQS_DISK_USR="460M"
186 + else
187 + CHECKREQS_DISK_BUILD="1400M"
188 + CHECKREQS_DISK_USR="450M"
189 + fi
190 +
191 + export CHECKREQS_DISK_BUILD CHECKREQS_DISK_USR
192 +}
193 +
194 +user_setup() {
195 + enewgroup ceph ${CEPH_GID}
196 + enewuser ceph "${CEPH_UID:--1}" -1 /var/lib/ceph ceph
197 +}
198 +
199 +pkg_pretend() {
200 + if use cephfs; then
201 + eerror "Cephfs support is broken in 13.2.2, please mask ${PF} if"
202 + eerror "you need cephfs support: "
203 + eerror " # echo '=${CATEGORY}/${PF}' >> /etc/portage/package.mask"
204 + eerror
205 + eerror "See https://bugs.gentoo.org/670592 for more information"
206 + die "CephFS support is currently broken"
207 + fi
208 +
209 + check-reqs_export_vars
210 + check-reqs_pkg_pretend
211 +}
212 +
213 +pkg_setup() {
214 + python_setup 'python3*'
215 + check-reqs_export_vars
216 + check-reqs_pkg_setup
217 + user_setup
218 +}
219 +
220 +src_prepare() {
221 + cmake-utils_src_prepare
222 +
223 + if use system-boost; then
224 + eapply "${FILESDIR}/ceph-13.2.0-boost-sonames.patch"
225 + fi
226 +
227 + sed -i -r "s:DESTINATION .+\\):DESTINATION $(get_bashcompdir)\\):" \
228 + src/bash_completion/CMakeLists.txt || die
229 +
230 + # remove tests that need root access
231 + rm src/test/cli/ceph-authtool/cap*.t || die
232 +
233 + #rm -rf "${UNBUNDLE_LIBS[@]}"
234 +}
235 +
236 +ceph_src_configure() {
237 + local flag
238 + local mycmakeargs=(
239 + -DWITH_BABELTRACE=$(usex babeltrace)
240 + -DWITH_CEPHFS=$(usex cephfs)
241 + -DWITH_DPDK=$(usex dpdk)
242 + -DWITH_FUSE=$(usex fuse)
243 + -DWITH_LTTNG=$(usex lttng)
244 + -DWITH_MGR=$(usex mgr)
245 + -DWITH_MGR_DASHBOARD_FRONTEND=NO
246 + -DWITH_OPENLDAP=$(usex ldap)
247 + -DWITH_RADOSGW=$(usex radosgw)
248 + -DWITH_SSL=$(usex ssl)
249 + -DWITH_SYSTEMD=$(usex systemd)
250 + -DWITH_TESTS=$(usex test)
251 + -DWITH_XFS=$(usex xfs)
252 + -DWITH_ZFS=$(usex zfs)
253 + -DENABLE_SHARED=$(usex static-libs '' 'yes' 'no')
254 + -DALLOCATOR=$(usex tcmalloc 'tcmalloc' "$(usex jemalloc 'jemalloc' 'libc')")
255 + -DWITH_SYSTEM_BOOST=$(usex system-boost)
256 + -DBOOST_J=$(makeopts_jobs)
257 + -DWITH_RDMA=no
258 + -DSYSTEMD_UNITDIR=$(systemd_get_systemunitdir)
259 + -DEPYTHON_VERSION="${EPYTHON#python}"
260 + -DCMAKE_INSTALL_DOCDIR="${EPREFIX}/usr/share/doc/${P}"
261 + -DCMAKE_INSTALL_SYSCONFDIR="${EPREFIX}/etc"
262 + -Wno-dev
263 + )
264 + if use amd64 || use x86; then
265 + for flag in ${CPU_FLAGS_X86[@]}; do
266 + mycmakeargs+=("$(usex cpu_flags_x86_${flag} "-DHAVE_INTEL_${flag^^}=1")")
267 + done
268 + fi
269 +
270 + rm -f "${BUILD_DIR:-${S}}/CMakeCache.txt"
271 + cmake-utils_src_configure
272 +
273 + # bug #630232
274 + sed -i "s:\"${T//:\\:}/${EPYTHON}/bin/python\":\"${PYTHON}\":" \
275 + "${BUILD_DIR:-${CMAKE_BUILD_DIR:-${S}}}"/include/acconfig.h \
276 + || die "sed failed"
277 +}
278 +
279 +src_configure() {
280 + ceph_src_configure
281 +}
282 +
283 +python_compile() {
284 + local CMAKE_USE_DIR="${S}"
285 + ceph_src_configure
286 +
287 + rm -r "${BUILD_DIR}/lib/cython_modules" || die
288 +
289 + pushd "${BUILD_DIR}/src/pybind" >/dev/null || die
290 + emake VERBOSE=1 clean
291 + emake VERBOSE=1 all
292 +
293 + # python modules are only compiled with "make install" so we need to do this to
294 + # prevent doing a bunch of compilation in src_install
295 + DESTDIR="${T}" emake VERBOSE=1 install
296 + popd >/dev/null || die
297 +}
298 +
299 +src_compile() {
300 + cmake-utils_src_make VERBOSE=1 all
301 +
302 + # we have to do this here to prevent from building everything multiple times
303 + BUILD_DIR="${CMAKE_BUILD_DIR}" python_copy_sources
304 + python_foreach_impl python_compile
305 +}
306 +
307 +src_test() {
308 + make check || die "make check failed"
309 +}
310 +
311 +python_install() {
312 + local CMAKE_USE_DIR="${S}"
313 + pushd "${BUILD_DIR}/src/pybind" >/dev/null || die
314 + DESTDIR="${ED}" emake install
315 + popd >/dev/null || die
316 +}
317 +
318 +src_install() {
319 + cmake-utils_src_install
320 + python_foreach_impl python_install
321 +
322 + prune_libtool_files --all
323 +
324 + exeinto /usr/$(get_libdir)/ceph
325 + newexe "${CMAKE_BUILD_DIR}/bin/init-ceph" ceph_init.sh
326 +
327 + insinto /etc/logrotate.d/
328 + newins "${FILESDIR}"/ceph.logrotate-r2 ${PN}
329 +
330 + keepdir /var/lib/${PN}{,/tmp} /var/log/${PN}/stat
331 +
332 + fowners -R ceph:ceph /var/lib/ceph /var/log/ceph
333 +
334 + newinitd "${FILESDIR}/rbdmap.initd" rbdmap
335 + newinitd "${FILESDIR}/${PN}.initd-r11" ${PN}
336 + newconfd "${FILESDIR}/${PN}.confd-r5" ${PN}
337 +
338 + insinto /etc/sysctl.d
339 + newins "${FILESDIR}"/sysctld 90-${PN}.conf
340 +
341 + use tcmalloc && newenvd "${FILESDIR}"/envd-tcmalloc 99${PN}-tcmalloc
342 +
343 + # units aren't installed by the build system unless systemd is enabled
344 + # so no point installing these with the USE flag disabled
345 + if use systemd; then
346 + systemd_install_serviced "${FILESDIR}/ceph-mds_at.service.conf" \
347 + "ceph-mds@.service"
348 +
349 + systemd_install_serviced "${FILESDIR}/ceph-osd_at.service.conf" \
350 + "ceph-osd@.service"
351 + fi
352 +
353 + udev_dorules udev/*.rules
354 +
355 + readme.gentoo_create_doc
356 +
357 + python_setup 'python3*'
358 +
359 + # bug #630232
360 + sed -i -r "s:${T//:/\\:}/${EPYTHON}:/usr:" "${ED}"/usr/bin/ceph \
361 + || die "sed failed"
362 +
363 + python_fix_shebang "${ED}"/usr/{,s}bin/
364 +
365 + # python_fix_shebang apparently is not idempotent
366 + sed -i -r 's:(/usr/lib/python-exec/python[0-9]\.[0-9]/python)[0-9]\.[0-9]:\1:' \
367 + "${ED}"/usr/{sbin/ceph-disk,bin/ceph-detect-init} || die "sed failed"
368 +}
369 +
370 +pkg_postinst() {
371 + readme.gentoo_print_elog
372 +}
373
374 diff --git a/sys-cluster/ceph/files/ceph.initd-r11 b/sys-cluster/ceph/files/ceph.initd-r11
375 new file mode 100644
376 index 00000000000..23827e1a562
377 --- /dev/null
378 +++ b/sys-cluster/ceph/files/ceph.initd-r11
379 @@ -0,0 +1,115 @@
380 +#!/sbin/openrc-run
381 +
382 +# make sure /etc/conf.d/ceph gets loaded for ceph-mon etc
383 +_CONFD_FILE="${RC_SERVICE%/*}/../conf.d/${RC_SVCNAME%-*}"
384 +if [ -r "${_CONFD_FILE}" ]; then
385 + . "${_CONFD_FILE}" || exit 1
386 +fi
387 +
388 +: "${ceph_conf:=/etc/ceph/ceph.conf}"
389 +daemon_type="${RC_SVCNAME#ceph-}"
390 +daemon_type="${daemon_type%%.*}"
391 +daemon_id="${RC_SVCNAME#ceph-*.}"
392 +daemon_id="${daemon_id:-0}"
393 +: "${rundir:=/run/ceph}"
394 +: "${user:=ceph}"
395 +: "${group:=ceph}"
396 +: "${rc_ulimit:=-n 1048576 -u 1048576}"
397 +
398 +pidfile="${rundir}/supervisor-${daemon_type}.${daemon_id}.pid"
399 +daemon_pidfile="${rundir}/${daemon_type}.${daemon_id}.pid"
400 +
401 +command="/usr/bin/${RC_SVCNAME%%.*}"
402 +command_args="-i ${daemon_id} --pid-file ${daemon_pidfile} -c ${ceph_conf}"
403 +extra_commands="reload"
404 +command_args_foreground="--foreground"
405 +
406 +retry="${CEPH_TERMTIMEOUT:-TERM/120/KILL/5}"
407 +start_stop_daemon_args="--user ${user} --group ${group}"
408 +supervise_daemon_args="--user ${user} --group ${group}"
409 +
410 +: "${supervisor:=supervise-daemon}"
411 +: "${stdout:=/var/log/ceph/ceph}"
412 +: "${stderr:=/var/log/ceph/ceph}"
413 +: "${respawn_delay:=10}"
414 +: "${respawn_max:=5}"
415 +: "${respawn_period:=1800}"
416 +
417 +: "${osd_respawn_delay:=15}"
418 +: "{osd_respawn_max:=10}"
419 +
420 +: "{radosgw_respawn_max:=5}"
421 +: "${radosgw_respawn_period:=30}"
422 +
423 +depend() {
424 + use dns logger
425 + after net ntpd ntp-client chronyd
426 + before netmount
427 +}
428 +
429 +is_type_valid() {
430 + case ${daemon_type} in
431 + mon|mds|osd|mgr|radosgw) return 0;;
432 + *) return 1;;
433 + esac
434 +}
435 +
436 +start_pre() {
437 + local log_dir
438 + export CEPH_CONF="${ceph_conf}"
439 +
440 + checkpath -d -q -o "${user}:${group}" "${rundir}"
441 +
442 + if ! is_type_valid ;then
443 + eerror "Please give valid Ceph Server Type: mds, mon, osd"
444 + return 1
445 +
446 + elif pgrep -f "[c]eph-${daemon_type} -i ${daemon_id} "; then
447 + eerror "${daemon_type}.${daemon_id} is still running, refusing to start"
448 + return 1
449 + fi
450 +
451 + if [ -n "${bluestore_osd_fsid}" ]; then
452 + einfo "Mounting Bluestore"
453 + ceph-volume lvm activate "${daemon_id}" "${bluestore_osd_fsid}" --no-systemd
454 + fi
455 +
456 + if [ "${daemon_type}" = radosgw ] && [ "${RADOSGW_WANT_NAME_PARAM}" = y ]; then
457 + command_args="${command_args} --name client.${daemon_id}"
458 + fi
459 +
460 + local arg_name arg_val repl_arg_name
461 + for arg_name in stdout stderr respawn_delay respawn_max respawn_period; do
462 + eval arg_val="\${${daemon_type}_${arg_name}}"
463 +
464 + if [ -z "${arg_val}" ]; then
465 + eval arg_val="\${${arg_name}}"
466 + else
467 + eval "${arg_name}=\"${arg_val}\""
468 + fi
469 +
470 + if [ "${arg_name}" = "stderr" ] || [ "${arg_name}" = "stdout" ]; then
471 + local log_file log_postfix
472 + log_postfix=".${daemon_id}-${arg_name}.log"
473 + log_file="${arg_val}"
474 +
475 + if [ "${log_file}" != /dev/null ]; then
476 + log_file="${log_file}${log_postfix}"
477 +
478 + log_dir="$(dirname "${log_file}")"
479 + checkpath -m 0755 -o "${user}:${group}" -d "${log_dir}"
480 + fi
481 +
482 + repl_arg_name="$(printf -- "%s\n" "${arg_name}" | tr _ -)"
483 + supervise_daemon_args="${supervise_daemon_args} --${repl_arg_name}=${log_file}"
484 + fi
485 + done
486 +}
487 +
488 +reload() {
489 + ebegin "Reloading Ceph ${daemon_type}.${daemon_id}"
490 + start-stop-daemon --signal 1 "${start_stop_daemon_args}"
491 + eend ${?}
492 +}
493 +
494 +# vim:ft=gentoo-init-d:ts=4:sts=4:sw=4:noet: