Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ports.sh « poudriere « share « src - github.com/freebsd/poudriere.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d08cdb871dd9c5792ac3df28de3f3908bca2f014 (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
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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
#!/bin/sh
# 
# Copyright (c) 2011-2013 Baptiste Daroussin <bapt@FreeBSD.org>
# Copyright (c) 2012-2013 Bryan Drewery <bdrewery@FreeBSD.org>
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.

. ${SCRIPTPREFIX}/common.sh

METHOD_DEF=git+https

# test if there is any args
usage() {
	cat << EOF
poudriere ports [parameters] [options]

Parameters:
    -c            -- Create a ports tree.
    -d            -- Delete a ports tree.
    -l            -- List all available ports trees.
    -u            -- Update a ports tree.

Options:
    -U url        -- URL where to fetch the ports tree from.
    -B branch     -- Which branch to use for the git or svn methods.
    -D            -- Do a full git clone without --depth (default: --depth=1)
    -F            -- When used with -c, only create the needed filesystems
                     (for ZFS) and directories, but do not populate them.
    -M path       -- The path to the source of a ports tree.
    -f filesystem -- The name of the filesystem to create for the ports tree.
                     If 'none' then do not create the filesystem.  The default
                     is: 'poudriere/ports/default'.
    -k            -- When used with -d, only unregister the ports tree without
                     removing the files.
    -m method     -- When used with -c, specify the method used to create the
                     ports tree. Can be one of:
		       'null', 'portsnap',
		       '{git,svn}{,+http,+https,+file,+ssh}' (e.g., 'git+https').
                     The default is '${METHOD_DEF}'.
    -n            -- When used with -l, only print the name of the ports tree
    -p name       -- Specifies the name of the ports tree to work on.  The
                     default is 'default'.
    -q            -- When used with -l, remove the header in the list view.
    -v            -- Show more verbose output.
EOF
	exit ${EX_USAGE}
}

FAKE=0
NAMEONLY=0
QUIET=0
KEEP=0
CREATED_FS=0
GIT_DEPTH=--depth=1
COMMAND=

set_command() {
	[ -z "${COMMAND}" ] || usage
	COMMAND="$1"
}

while getopts "B:cDFuU:dklp:qf:nM:m:v" FLAG; do
	case "${FLAG}" in
		B)
			BRANCH="${OPTARG}"
			;;
		c)
			set_command create
			;;
		D)
			GIT_DEPTH=""
			;;
		F)
			FAKE=1
			;;
		u)
			set_command update
			;;
		U)
			SOURCES_URL=${OPTARG}
			;;
		n)
			NAMEONLY=1
			;;
		p)
			PTNAME=${OPTARG}
			;;
		d)
			set_command delete
			;;
		k)
			KEEP=1
			;;
		l)
			set_command list
			;;
		q)
			QUIET=1
			;;
		f)
			PTFS=${OPTARG}
			;;
		M)
			PTMNT=${OPTARG}
			;;
		m)
			METHOD=${OPTARG}
			;;
		v)
			VERBOSE=$((VERBOSE + 1))
			;;
		*)
			usage
		;;
	esac
done

saved_argv="$@"
shift $((OPTIND-1))
post_getopts

[ ${FAKE} -eq 0 ] && METHOD=${METHOD:-${METHOD_DEF}}
PTNAME=${PTNAME:-default}

[ "${METHOD}" = "none" ] && METHOD=null

# Handle common (jail+ports) git/svn methods and then fallback to
# methods only supported by jail.
if ! svn_git_checkout_method "${SOURCES_URL}" "${METHOD}" \
    "${SVN_HOST}/ports" "${GIT_PORTSURL}" \
    METHOD SVN_FULLURL GIT_FULLURL; then
	if [ -n "${SOURCES_URL}" ]; then
		usage
	fi
	case "${METHOD}" in
	portsnap) ;;
	null) ;;
	*)
		if [ ${FAKE} -eq 0 ]; then
			msg_error "Unknown method ${METHOD}"
			usage
		fi
		;;
	esac
fi

case ${METHOD} in
svn*) : ${BRANCH:=head} ;;
git*) ;;
*)
	[ -n "${BRANCH}" ] && \
	    err 1 "Branch (-B) only supported for SVN and git."
esac

cleanup_new_ports() {
	msg "Error while creating ports tree, cleaning up." >&2
	if [ "${CREATED_FS}" -eq 1 ] && [ "${METHOD}" != "null" ]; then
		TMPFS_ALL=0 destroyfs ${PTMNT} ports || :
	fi
	rm -rf ${POUDRIERED}/ports/${PTNAME} || :
}

check_portsnap_interactive() {
	if /usr/sbin/portsnap --help | grep -q -- '--interactive'; then
		echo "--interactive "
	fi
}

if [ "${COMMAND}" != "list" ]; then
	[ -z "${PTNAME}" ] && usage
fi

case $COMMAND in
list)
	if [ ${NAMEONLY} -eq 0 ]; then
		format='%%-%ds %%-%ds %%-%ds %%-%ds\n'
		display_setup "${format}" "-d"
		display_add "PORTSTREE" "METHOD" "TIMESTAMP" "PATH"
	else
		format='%s'
		display_setup "${format}" "-d"
		display_add "PORTSTREE"
	fi
	while read ptname ptmethod ptpath; do
		[ -z "${ptname}" ] && break
		if [ ${NAMEONLY} -eq 0 ]; then
			_pget timestamp ${ptname} timestamp || :
			time=
			[ -n "${timestamp}" ] && \
			    time="$(date -j -r ${timestamp} "+%Y-%m-%d %H:%M:%S")"
			display_add ${ptname} ${ptmethod} "${time}" ${ptpath}
		else
			display_add ${ptname}
		fi
	done <<- EOF
	$(porttree_list)
	EOF
	[ ${QUIET} -eq 1 ] && quiet="-q"
	display_output ${quiet}
	;;

create)
	[ ${VERBOSE} -gt 0 ] || quiet="-q"
	# test if it already exists
	porttree_exists ${PTNAME} && err 2 "The ports tree, ${PTNAME}, already exists"
	maybe_run_queued "${saved_argv}"
	: ${PTMNT="${BASEFS:=/usr/local${ZROOTFS}}/ports/${PTNAME}"}
	: ${PTFS="${ZPOOL}${ZROOTFS}/ports/${PTNAME}"}

	case "${PTNAME}" in
	*:*)
		err 1 "The ports name cannot contain a period (.). See jail(8)"
		;;
	*-*)
		err 1 "The ports name should not contain a dash (-). Poudriere will parse it as a SETNAME (-z)."
		;;
	esac

	if [ "${METHOD}" = "null" ]; then
		[ -z "${PTMNT}" ] && \
		    err 1 "Must set -M to path of ports tree to use"
		[ "${PTMNT}" = "/" ] && \
		    err 1 "Cannot use / for -M"
		PTFS="none"
		[ ${FAKE} -eq 1 ] && err 1 "Cannot use -F with -m null"
	fi

	[ "${PTFS}" != "none" ] && [ -d "${PTMNT}" ] && \
	    err 1 "Directory ${PTMNT} already exists"

	if [ "${METHOD}" != "null" ]; then
		# This will exit if it fails to zfs create...
		createfs ${PTNAME} ${PTMNT} ${PTFS:-none}
		# Ports runs without -e, but even if it did let's not
		# short-circuit all of -e support in createfs.  It
		# should have exited on error with err(), but be sure.
		if [ $? -eq 0 ]; then
			CREATED_FS=1
		fi
	fi

	# Wrap the ports creation in a special cleanup hook that will remove it
	# if any error is encountered
	CLEANUP_HOOK=cleanup_new_ports

	pset ${PTNAME} mnt ${PTMNT}
	pset ${PTNAME} created_fs ${CREATED_FS}
	if [ $FAKE -eq 0 ]; then
		case ${METHOD} in
		portsnap)
			# additional portsnap arguments
			PTARGS=$(check_portsnap_interactive)
			mkdir ${PTMNT}/.snap
			msg "Extracting portstree \"${PTNAME}\"..."
			/usr/sbin/portsnap ${PTARGS} -d ${PTMNT}/.snap -p ${PTMNT} fetch extract ||
			/usr/sbin/portsnap ${PTARGS} -d ${PTMNT}/.snap -p ${PTMNT} fetch extract ||
			    err 1 " fail"
			;;
		svn*)
			if [ ! -x "${SVN_CMD}" ]; then
				err 1 "svn or svnlite not installed. Perhaps you need to 'pkg install subversion'"
			fi

			msg_n "Checking out the ports tree..."
			${SVN_CMD} ${quiet} co \
				${SVN_PRESERVE_TIMESTAMP} \
				${SVN_FULLURL}/${BRANCH} \
				${PTMNT} || err 1 " fail"
			echo " done"
			;;
		git*)
			# !! Any changes here should be considered for jail.sh too.
			if [ ! -x "${GIT_CMD}" ]; then
				err 1 "Git is not installed. Perhaps you need to 'pkg install git'"
			fi
			msg_n "Cloning the ports tree..."
			${GIT_CMD} clone ${GIT_DEPTH} ${quiet} \
			    ${BRANCH:+-b ${BRANCH}} ${GIT_FULLURL} ${PTMNT} || \
			    err 1 " fail"
			echo " done"
			;;
		esac
		pset ${PTNAME} method ${METHOD}
		pset ${PTNAME} timestamp $(clock -epoch)
	else
		pset ${PTNAME} method ${METHOD:--}
	fi
	if [ "${METHOD}" = "null" ]; then
		msg "Imported ports tree \"${PTNAME}\" from ${PTMNT}"
	fi

	unset CLEANUP_HOOK
	;;

delete)
	porttree_exists ${PTNAME} || err 2 "No such ports tree ${PTNAME}"
	PTMETHOD=$(pget ${PTNAME} method)
	PTMNT=$(pget ${PTNAME} mnt)
	CREATED_FS=$(pget ${PTNAME} created_fs || echo 0)
	[ -d "${PTMNT}/ports" ] && PORTSMNT="${PTMNT}/ports"
	${NULLMOUNT} | /usr/bin/grep -q "${PORTSMNT:-${PTMNT}} on" \
		&& err 1 "Ports tree \"${PTNAME}\" is currently mounted and being used."
	confirm_if_tty "Are you sure you want to delete the ports tree ${PTNAME} at ${PTMNT}?" || \
	    err 1 "Not deleting ports tree"
	maybe_run_queued "${saved_argv}"
	msg_n "Deleting portstree \"${PTNAME}\"..."
	# Regarding -F, older system ports trees will have method=- and
	# created_fs=0 so we never delete them (#250).
	# Newer imports with -F will have method=- and could have
	# created_fs=1 if they did not use -m null.  It is fine to
	# delete in that case (#469)
	if [ ${KEEP} -eq 0 -a "${PTMETHOD}" != "null" -a \
	    "${PTMETHOD}" != "none" ]; then
		can_delete=1

		# Deal with method=-
		[ "${PTMETHOD}" = "-" ] && can_delete=${CREATED_FS}
		if [ ${can_delete} -eq 1 ]; then
			TMPFS_ALL=0 destroyfs ${PTMNT} ports || :
		fi
	fi
	rm -rf ${POUDRIERED}/ports/${PTNAME} || :
	echo " done"
	;;

update)
	[ ${VERBOSE} -gt 0 ] || quiet="-q"
	porttree_exists ${PTNAME} || err 2 "No such ports tree ${PTNAME}"
	METHOD=$(pget ${PTNAME} method)
	PTMNT=$(pget ${PTNAME} mnt)
	[ -d "${PTMNT}/ports" ] && PORTSMNT="${PTMNT}/ports"
	${NULLMOUNT} | /usr/bin/grep -q "${PORTSMNT:-${PTMNT}} on" \
		&& err 1 "Ports tree \"${PTNAME}\" is currently mounted and being used."
	maybe_run_queued "${saved_argv}"
	if [ -z "${METHOD}" -o ${METHOD} = "-" ]; then
		METHOD=${METHOD_DEF}
		pset ${PTNAME} method ${METHOD}
	fi
	case ${METHOD} in
	portsnap|"")
		msg_n "Updating portstree \"${PTNAME}\" with ${METHOD}..."
		# additional portsnap arguments
		PTARGS=$(check_portsnap_interactive)
		if [ -d "${PTMNT}/snap" ]; then
			SNAPDIR=${PTMNT}/snap
		else
			SNAPDIR=${PTMNT}/.snap
		fi
		/usr/sbin/portsnap ${PTARGS} -d ${SNAPDIR} -p ${PORTSMNT:-${PTMNT}} ${PSCOMMAND} alfred || \
		    err 1 " fail"
		echo " done"
		;;
	svn*)
		msg_n "Updating portstree \"${PTNAME}\" with ${METHOD}..."
		${SVN_CMD} upgrade ${PORTSMNT:-${PTMNT}} 2>/dev/null || :
		${SVN_CMD} ${quiet} update \
			${SVN_PRESERVE_TIMESTAMP} \
			${PORTSMNT:-${PTMNT}} || \
		    err 1 " fail"
		echo " done"
		;;
	git*)
		# !! Any changes here should be considered for jail.sh too.
		msg_n "Updating portstree \"${PTNAME}\" with ${METHOD}..."
		${GIT_CMD} -C ${PORTSMNT:-${PTMNT}} pull --rebase ${quiet} || \
		    err 1 " fail"
		echo " done"
		;;
	null|none) msg "Not updating portstree \"${PTNAME}\" with method ${METHOD}" ;;
	*)
		err 1 "Undefined upgrade method"
		;;
	esac

	pset ${PTNAME} timestamp $(clock -epoch)
	run_hook ports_update "done"
	;;

*)
	usage
	;;
esac