Check-in [d7a00fbd93]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Sync with trunk (resolve 1 conflict)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dragonfly
Files: files | file ages | folders
SHA1:d7a00fbd93bf97b6888a1bf85efae4ade4dc2796
User & Date: marino 2013-04-17 16:48:22
Context
2013-04-20
01:15
WIP: Merge DragonFly bits from 2.3 -- untested check-in: ba3ea6d217 user: marino tags: dragonfly
2013-04-17
16:48
Sync with trunk (resolve 1 conflict) check-in: d7a00fbd93 user: marino tags: dragonfly
13:24
Check for <tree>-options as well check-in: c9d23c4740 user: bdrewery tags: trunk
2013-04-01
22:27
manpage/conf: Bring in DragonFly changes This is basically a test commit. check-in: 879cb1fde0 user: marino tags: dragonfly
Changes

Changes to README.

15
16
17
18
19
20
21






22
23
24
25
26
27
28
29
30

http://fossil.etoilebsd.net/poudriere/doc/trunk/doc/index.wiki

A copy of this documentation could be found in the doc directory.

You can also open the manpage of poudriere, located in the 8th section.







Getting started with poudriere
------------------------------

1. Install it by typing "make install" at the top-level directory
2. Copy /usr/local/etc/poudriere.conf.sample to /usr/local/etc/poudriere.conf
3. Edit it to suit your needs
4. man poudriere, search for EXAMPLES
5. Follow "bulk build of binary packages" steps
6. Enjoy your new fresh binary packages!







>
>
>
>
>
>









15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

http://fossil.etoilebsd.net/poudriere/doc/trunk/doc/index.wiki

A copy of this documentation could be found in the doc directory.

You can also open the manpage of poudriere, located in the 8th section.

Support
-------

IRC:          #poudriere on freenode
Mailing list: freebsd-pkg@FreeBSD.org

Getting started with poudriere
------------------------------

1. Install it by typing "make install" at the top-level directory
2. Copy /usr/local/etc/poudriere.conf.sample to /usr/local/etc/poudriere.conf
3. Edit it to suit your needs
4. man poudriere, search for EXAMPLES
5. Follow "bulk build of binary packages" steps
6. Enjoy your new fresh binary packages!

Changes to conf/poudriere.conf.sample.

137
138
139
140
141
142
143









# ALLOW_MAKE_JOBS=yes


# Define as the URL that your POUDRIERE_DATA/logs is hosted at
# This will be used for giving URL hints to the HTML output when
# scheduling and starting builds
#URL_BASE=http://yourdomain.com/poudriere/
















>
>
>
>
>
>
>
>
>
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# ALLOW_MAKE_JOBS=yes


# Define as the URL that your POUDRIERE_DATA/logs is hosted at
# This will be used for giving URL hints to the HTML output when
# scheduling and starting builds
#URL_BASE=http://yourdomain.com/poudriere/


# This defines the max time (in seconds) that a command may run for a build
# before it is killed for taking too long. Default: 86400
#MAX_EXECUTION_TIME=86400

# This defines the how long (in seconds) before a command is considered to
# be in a runaway state for having no output on stdout. Default: 7200
#NOHANG_TIME=7200

Changes to doc/index.wiki.

55
56
57
58
59
60
61











62
63
64
  *  [./pkgng_repos.wiki|...create and maintain pkgng repositories]
  *  [./portshaker.wiki|...manage poudriere ports using portshaker]
  *  [./portmaster.wiki|...use the generated packages with portmaster]
  *  [./ccache.wiki|...use ccache with poudriere]
  *  [./config.wiki|...easily generate options]
  *  [./use_system_ports_tree.wiki|...use the system ports tree in poudriere]












Happy FreeBSDing!

Join us on IRC: #poudriere on Freenode







>
>
>
>
>
>
>
>
>
>
>



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  *  [./pkgng_repos.wiki|...create and maintain pkgng repositories]
  *  [./portshaker.wiki|...manage poudriere ports using portshaker]
  *  [./portmaster.wiki|...use the generated packages with portmaster]
  *  [./ccache.wiki|...use ccache with poudriere]
  *  [./config.wiki|...easily generate options]
  *  [./use_system_ports_tree.wiki|...use the system ports tree in poudriere]

<h1>Hacking </h1>

To hack on poudriere you first need to use [fossil|http://fossil-scm.org]

and clone the repo:

<verbatim># fossil clone https://fossil.etoilebsd.net/poudriere poudriere.fossil
# mkdir poudriere
# cd poudriere
# fossil open ../poudriere.fossil</verbatim>

Happy FreeBSDing!

Join us on IRC: #poudriere on Freenode

Changes to doc/pkgng_repos.wiki.

1
2
3
4
5
6
7
8
9
10
..
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
..
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



<h1>creating pkgng repositories</h1>

Install poudriere and pkgng on the host (please note that the host do not need
to be converted to pkgng)

    <verbatim>make -C /usr/ports/ports-mgmt/poudriere install clean
make -C /usr/ports/ports-mgmt/pkg install clean</verbatim>

Create a default configuration in the ${LOCALBASE}/etc/poudriere.conf
configuration file: 
................................................................................
FREEBSD_HOST=ftp://ftp.freebsd.org
POUDRIERE_DATA=/poudriere_data
RESOLV_CONF=/etc/resolv.conf
DISTFILES_CACHE=/usr/ports/distfiles</verbatim>

poudriere is now ready to be used.

First create a ports tree to be used by poudriere 

    <verbatim>poudriere ports -c</verbatim>

Create the jail in version you want to build packages for: 

    <verbatim>poudriere jail -c -j 90amd64 -v 9.0-RELEASE -a amd64
poudriere jail -c -j 10i386 -v head -a i386 -m svn</verbatim>

The first will create a 9.0-RELEASE amd64 jail from the official sets (fetched
on FREEBSD_HOST) The second will create a current jail using svn and build for
i386

As poudriere works for both legacy pkg_* and pkgng you need to make it pkgng
aware: 

    <verbatim>mkdir /usr/local/etc/poudriere.d
echo "WITH_PKGNG=yes" > /usr/local/etc/poudriere.d/90amd64-make.conf
echo "WITH_PKGNG=yes" > /usr/local/etc/poudriere.d/10i386-make.conf</verbatim>
................................................................................
editors/vim-lite
www/nginx</verbatim>

    <verbatim>cat ~/mylist2
www/firefox
editors/libreoffice</verbatim>

Just run poudriere: 

    <verbatim>poudriere bulk -f ~/mylist1 -j 90amd64
poudriere bulk -f ~/mylist2 -j 10i386</verbatim>

This will built 2 pkgng repositories:

  *  ${POUDRIERE_DATA}/packages/10i386-default
  *  ${POUDRIERE_DATA}/packages/90amd64-default 

Configure you http server to those directories to be able to serve them.

On your user boxes: (if you use the automatic bootstrap it will take
care of creating this file) 

    <verbatim>echo "packagesite: http://yoururl/10i386-default" >> /usr/local/etc/pkg.conf</verbatim>
    <verbatim>echo "packagesite: http://yoururl/90amd64-default" >> /usr/local/etc/pkg.conf</verbatim>

From 9.1 you can directly bootstrap from the base:

    <verbatim>PACKAGESITE="http://yoururl/10i386-default" pkg update</verbatim>

Before 9.1 you will need to boostrap by hand:

    <verbatim>fetch http://yoururl/90amd64-default/Latest/pkg.txz
tar xf ./pkg.txz -s ",/.*/,,g" "*/pkg-static"
./pkg-static add ./pkg.txz</verbatim>

To update your repositories just rerun poudriere bulk. By default, the build
will be incremental, and reuse packages from the previous run. Use -c to clear
all packages and build fresh.

    <verbatim>poudriere ports -u # this update your default ports tree

poudriere bulk -f ~/mylist1 -j 90amd64
poudriere bulk -f ~/mylist2 -j 10i386</verbatim>





|







 







|









|
|







 







|




|




|







|



|





|
|
<
<
|
>
|

>
>
>
1
2
3
4
5
6
7
8
9
10
..
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
..
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
<h1>creating pkgng repositories</h1>

Install poudriere and pkgng on the host (please note that the host does not need
to be converted to pkgng)

    <verbatim>make -C /usr/ports/ports-mgmt/poudriere install clean
make -C /usr/ports/ports-mgmt/pkg install clean</verbatim>

Create a default configuration in the ${LOCALBASE}/etc/poudriere.conf
configuration file: 
................................................................................
FREEBSD_HOST=ftp://ftp.freebsd.org
POUDRIERE_DATA=/poudriere_data
RESOLV_CONF=/etc/resolv.conf
DISTFILES_CACHE=/usr/ports/distfiles</verbatim>

poudriere is now ready to be used.

First create a ports tree to be used by poudriere:

    <verbatim>poudriere ports -c</verbatim>

Create the jail in version you want to build packages for: 

    <verbatim>poudriere jail -c -j 90amd64 -v 9.0-RELEASE -a amd64
poudriere jail -c -j 10i386 -v head -a i386 -m svn</verbatim>

The first will create a 9.0-RELEASE amd64 jail from the official sets (fetched
from FREEBSD_HOST) The second will create a current jail using svn and build for
i386.

As poudriere works for both legacy pkg_* and pkgng you need to make it pkgng
aware: 

    <verbatim>mkdir /usr/local/etc/poudriere.d
echo "WITH_PKGNG=yes" > /usr/local/etc/poudriere.d/90amd64-make.conf
echo "WITH_PKGNG=yes" > /usr/local/etc/poudriere.d/10i386-make.conf</verbatim>
................................................................................
editors/vim-lite
www/nginx</verbatim>

    <verbatim>cat ~/mylist2
www/firefox
editors/libreoffice</verbatim>

Start a poudriere build run:

    <verbatim>poudriere bulk -f ~/mylist1 -j 90amd64
poudriere bulk -f ~/mylist2 -j 10i386</verbatim>

This will build two pkgng repositories:

  *  ${POUDRIERE_DATA}/packages/10i386-default
  *  ${POUDRIERE_DATA}/packages/90amd64-default 

Configure an http server to serve these directories.

On your user boxes: (if you use the automatic bootstrap it will take
care of creating this file) 

    <verbatim>echo "packagesite: http://yoururl/10i386-default" >> /usr/local/etc/pkg.conf</verbatim>
    <verbatim>echo "packagesite: http://yoururl/90amd64-default" >> /usr/local/etc/pkg.conf</verbatim>

From FreeBSD 9.1 and later it is possible to directly bootstrap from the base:

    <verbatim>PACKAGESITE="http://yoururl/10i386-default" pkg update</verbatim>

Before FreeBSD 9.1, it is necessary to bootstrap by hand:

    <verbatim>fetch http://yoururl/90amd64-default/Latest/pkg.txz
tar xf ./pkg.txz -s ",/.*/,,g" "*/pkg-static"
./pkg-static add ./pkg.txz</verbatim>

Normal operation after the needed build jails have been created looks like:
 * Update the poudriere ports tree:


    <verbatim>poudriere ports -u</verbatim>
 * Run an incremental build on both build jails:
    <verbatim>poudriere bulk -f ~/mylist1 -j 90amd64
poudriere bulk -f ~/mylist2 -j 10i386</verbatim>

It might become necessary to do a full fresh build, use the -c flag to bulk to
clear all packages and build fresh.

Changes to poudriere.8.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
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
...
499
500
501
502
503
504
505

506

507

508
509
510
511
512
513
514
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.\" Note: The date here should be updated whenever a non-trivial
.\" change is made to the manual page.
.Dd March 21, 2013
.Dt POUDRIERE 8
.Os FreeBSD
.Sh NAME
.Nm poudriere
.Nd bulk package builder and port tester
.Sh SYNOPSIS
.Nm
................................................................................
.Ar YYYY-MM-DD_HH:MM:SS
will be used.
This can be used to resume a previous build and use the same log and URL paths.
.It Fl c
This flag specifies to clean the previous built binary packages.
.It Fl C
Clean previous packages for the given list to build.



.It Fl j Ar name
If given, run the bulk build only on the jail named
.Ar name .
.It Fl J Ar number
This argument specifies how many
.Ar number
jobs will run in parallel for a bulk build.


.It Fl p Ar tree
This flag specifies on which ports
.Ar tree
the bulk build will be done.
.It Fl s
Skip sanity tests.
Sanity tests are made to check if the ports exists,
does not have an increased version number, and if the compiled options
match the current options from the make.conf files and /var/db/options.
.It Fl t
Add some testing.
Currently uninstalls the port, and disable parallel
jobs for make.


.It Fl w
Save WRKDIR on build failure.
The WRKDIR will be tarred up into
.Sy ${POUDRIERE_DATA}/wrkdirs .
.It Fl v
This will show more information during the build.
Specify twice to enable debug output.
................................................................................
.Ss Custom build options
Before building a package,
.Nm
can mount a directory containing option files if available.
.Nm
will check for any of these directories in this order:
.Pp

.Dl /usr/local/etc/poudriere.d/<jailname>-<setname>-options

.Dl /usr/local/etc/poudriere.d/<setname>-options

.Dl /usr/local/etc/poudriere.d/<jailname>-options
.Dl /usr/local/etc/poudriere.d/options
.Pp
If a directory with this name exists, it is null-mounted into the
/var/db/ports/ directory of the jail, thus allowing to build package
with custom OPTIONS.
.Pp







|







 







>
>
>







>
>













>
>







 







>

>

>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
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
...
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.\" Note: The date here should be updated whenever a non-trivial
.\" change is made to the manual page.
.Dd April 17, 2013
.Dt POUDRIERE 8
.Os FreeBSD
.Sh NAME
.Nm poudriere
.Nd bulk package builder and port tester
.Sh SYNOPSIS
.Nm
................................................................................
.Ar YYYY-MM-DD_HH:MM:SS
will be used.
This can be used to resume a previous build and use the same log and URL paths.
.It Fl c
This flag specifies to clean the previous built binary packages.
.It Fl C
Clean previous packages for the given list to build.
.It Fl F
Only fetch from original MASTER_SITES.
Skip FreeBSD mirrors.
.It Fl j Ar name
If given, run the bulk build only on the jail named
.Ar name .
.It Fl J Ar number
This argument specifies how many
.Ar number
jobs will run in parallel for a bulk build.
.It Fl N
Do not build package repository or INDEX when build is completed.
.It Fl p Ar tree
This flag specifies on which ports
.Ar tree
the bulk build will be done.
.It Fl s
Skip sanity tests.
Sanity tests are made to check if the ports exists,
does not have an increased version number, and if the compiled options
match the current options from the make.conf files and /var/db/options.
.It Fl t
Add some testing.
Currently uninstalls the port, and disable parallel
jobs for make.
.It Fl T
Try building BROKEN ports by defining TRYBROKEN for the build.
.It Fl w
Save WRKDIR on build failure.
The WRKDIR will be tarred up into
.Sy ${POUDRIERE_DATA}/wrkdirs .
.It Fl v
This will show more information during the build.
Specify twice to enable debug output.
................................................................................
.Ss Custom build options
Before building a package,
.Nm
can mount a directory containing option files if available.
.Nm
will check for any of these directories in this order:
.Pp
.Dl /usr/local/etc/poudriere.d/<jailname>-<tree>-<setname>-options
.Dl /usr/local/etc/poudriere.d/<jailname>-<setname>-options
.Dl /usr/local/etc/poudriere.d/<jailname>-<tree>-options
.Dl /usr/local/etc/poudriere.d/<setname>-options
.Dl /usr/local/etc/poudriere.d/<tree>-options
.Dl /usr/local/etc/poudriere.d/<jailname>-options
.Dl /usr/local/etc/poudriere.d/options
.Pp
If a directory with this name exists, it is null-mounted into the
/var/db/ports/ directory of the jail, thus allowing to build package
with custom OPTIONS.
.Pp

Changes to src/libexec/poudriere/Makefile.

1
2





3
4
5
6

7
8
9
10


11
12
13
PREFIX?=	/usr/local






dirwatch: dirwatch.c
	${CC} -Wall -Werror ${CFLAGS} dirwatch.c -o dirwatch

All: dirwatch


install: dirwatch
	mkdir -p ${PREFIX}/libexec/poudriere
	install -m 755 -o root -g wheel dirwatch ${PREFIX}/libexec/poudriere



clean:
	rm -f dirwatch


>
>
>
>
>



|
>

|


>
>


|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PREFIX?=	/usr/local

all: dirwatch make_index dirempty

dirempty: dirempty.c
	${CC} -Wall -Werror ${CFLAGS} dirempty.c -o dirempty

dirwatch: dirwatch.c
	${CC} -Wall -Werror ${CFLAGS} dirwatch.c -o dirwatch

make_index: make_index.c
	${CC} -Wall -Werror ${CFLAGS} make_index.c -o make_index -lsbuf

install: dirwatch make_index dirempty
	mkdir -p ${PREFIX}/libexec/poudriere
	install -m 755 -o root -g wheel dirwatch ${PREFIX}/libexec/poudriere
	install -m 755 -o root -g wheel make_index ${PREFIX}/libexec/poudriere
	install -m 755 -o root -g wheel dirempty ${PREFIX}/libexec/poudriere

clean:
	rm -f dirwatch make_index dirempty

Added src/libexec/poudriere/dirempty.c.



































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
/*-
 * Copyright (c) 2013 Baptiste Daroussin <bapt@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
 *    in this position and unchanged.
 * 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(S) ``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(S) 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.
 */

#include <sys/types.h>
#include <stdbool.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <err.h>
 
bool
dir_empty(const char *path)
{
	struct dirent *ent;
	bool ret = true;
	DIR *d;

	if ((d = opendir(path)) == NULL)
		err(EXIT_FAILURE, "%s: ", path);

	while ((ent = readdir(d))) {
		if (strcmp(ent->d_name, ".") == 0 || (strcmp(ent->d_name, "..")) == 0)
			continue;
		ret = false;
		break;
	}
	closedir(d);

	return (ret);
}
 
int
main(int argc, char **argv)
{
	if (argc != 2)
		err(EXIT_FAILURE, "Argument missing");
 
	if (dir_empty(argv[1]))
		return (EXIT_SUCCESS);

	return (EXIT_FAILURE);
}

Changes to src/libexec/poudriere/dirwatch.c.


























1
2
3
4
5
6
7

























#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/stat.h>

#include <unistd.h>
#include <fcntl.h>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
/*-
 * Copyright (c) 2013 Baptiste Daroussin <bapt@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
 *    in this position and unchanged.
 * 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(S) ``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(S) 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.
 */
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/stat.h>

#include <unistd.h>
#include <fcntl.h>

Added src/libexec/poudriere/make_index.c.























































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
/*
 * Copyright (c) 2013 David Demelier <demelier.david@gmail.com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/types.h>
#include <sys/sbuf.h>
#include <sys/queue.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <err.h>

/*
 * A field, it helps defining the list of fields such as depends
 * in the line. They are usually separated by spaces. We also
 * define a datatype FieldList which contains all fields.
 */
typedef struct Field Field;

struct Field {
	char		*value;
	STAILQ_ENTRY(Field) link;
};

typedef STAILQ_HEAD(, Field) FieldList;

/*
 * A port, has some fields and list of fields (such as depends). We also
 * define a datatype Ports which contains all ports listed in the
 * index.
 */
typedef struct Port Port;

struct Port {
	char		*name;
	char		*portpath;
	char		*prefix;
	char		*comment;
	char		*descfile;
	char		*maintainer;
	char		*categories;			/* A list but no need to split */
	char		*www;

	/* The following may be lists */
	FieldList	edepends;		/* extract deps */
	FieldList	pdepends;		/* patch depends */
	FieldList	fdepends;		/* fetch depends */
	FieldList	bdepends;		/* build depends */
	FieldList	rdepends;		/* run depends */

	STAILQ_ENTRY(Port) link;
};

typedef STAILQ_HEAD(, Port) Ports;

/*
 * Enumerate the index of some values in the index line. Documented
 * in the make describe target in ports/Mk/bsd.port.mk.
 */
typedef enum Value {
	ValueName	= 0,
	ValuePortPath,
	ValuePrefix,
	ValueComment,
	ValueDescription,
	ValueMaintainer,
	ValueCategories,
	ValueEDepends,
	ValuePDepends,
	ValueFDepends,
	ValueBDepends,
	ValueRDepends,
	ValueWWW,
	ValueLAST
} Value;

/* --------------------------------------------------------
 * Allocation helpers
 * -------------------------------------------------------- */

static void *
xmalloc(size_t size)
{
	void *ptr;

	if ((ptr = calloc(1, size)) == NULL)
		err(1, "malloc");

	return ptr;
}

static char *
xstrdup(const char *src)
{
	char *str;

	if ((str = strdup(src)) == NULL)
		err(1, "strdup");

	return str;
}

static void
usage(void)
{
	errx(1, "usage: %s oldindex newindex", getprogname());
}

/* --------------------------------------------------------
 * Field functions
 * -------------------------------------------------------- */

static Port * ports_find(const Ports *, const char *);

/*
 * Add the dependency only if not present. We will retrieve
 * the name of the port from the list
 */
static void
add_dep(FieldList *full, const Ports *ports, const Field *name)
{
	Port *port;
	Field *field, *n;
	bool found = false;	

	STAILQ_FOREACH(field, full, link)
		if (strcmp(field->value, name->value) == 0) {
			found = true;
			break;
		}

	if (!found) {
		port = ports_find(ports, name->value);
		n = xmalloc(sizeof (Field));
		n->value = xstrdup(port->portpath);
		STAILQ_INSERT_TAIL(full, n, link);
	}

}

/*
 * Split the list of dependencies by spaces and append it to the field
 * list.
 */
static void
field_list_fill(FieldList *fields, const char *line)
{
	char *word, *string, *tofree;
	Field *field;

	string = tofree = strdup(line);
	STAILQ_INIT(fields);

	if (strlen(line) > 0) {
		while ((word = strsep(&string, " \t")) != NULL) {
			if (strlen(word) > 0) {
				field		= xmalloc(sizeof (Field));
				field->value	= xstrdup(word);
				STAILQ_INSERT_TAIL(fields, field, link);
			}
		}
	}

	free(tofree);
}

/*
 * Prepare a list of dependencies to add, we also add the run depends of the
 * depends.
 */
static void
fields_list_catdeps(FieldList *full, const FieldList *deps, const Ports *ports)
{
	Field *field, *field2;
	Port *port;

	STAILQ_INIT(full);
	STAILQ_FOREACH(field, deps, link) {
		add_dep(full, ports, field);

		/* For that depend, find run depends of it */	
		port = ports_find(ports, field->value);

		STAILQ_FOREACH(field2, &port->rdepends, link)
			add_dep(full, ports, field2);
	}
}

/*
 * Free the list of fields.
 */
static void
fields_list_free(FieldList *fields)
{
	Field *field, *tmp;

	STAILQ_FOREACH_SAFE(field, fields, link, tmp) {
		free(field->value);
		free(field);
	}
}

/* --------------------------------------------------------
 * Ports functions
 * -------------------------------------------------------- */

/*
 * Split the line into the values separeted by '|'.
 */
static void
line_split(char *values[ValueLAST], const char *line)
{
	char *word, *string, *tofree;
	int i = 0;

	string = tofree = xstrdup(line);
	while ((word = strsep(&string, "|")) != NULL)
		values[i++] = xstrdup(word);

	free(tofree);
}

/*
 * Build a list of depends and write it to the depends.
 */
static void
buf_add_depends(struct sbuf *sbuf, const FieldList *fields, const Ports *ports,
    bool append_sep)
{
	Port *port;
	Field *field;
	FieldList depends;
	bool last;

	fields_list_catdeps(&depends, fields, ports);
	STAILQ_FOREACH(field, &depends, link) {
		last = STAILQ_LAST(&depends, Field, link) == field;
		port = ports_find(ports, field->value);
		sbuf_printf(sbuf, "%s%s", port->name, (last) ? "" : " ");
	}

	fields_list_free(&depends);
	if (append_sep)
		sbuf_putc(sbuf, '|');
}

/*
 * Add a port to the list, will split the line and extract information
 * to that port.
 */
static void
ports_add(Ports *ports, const char *line)
{
	Port *port;
	char *values[ValueLAST] = { NULL };

	line_split(values, line);
	
	/*
	 * Do not duplicate the values[] string because they were
	 * already strdup'ed() from the split_line function.
	 */
	port			= xmalloc(sizeof (Port));
	port->name		= values[ValueName];
	port->portpath		= values[ValuePortPath];
	port->prefix		= values[ValuePrefix];
	port->comment		= values[ValueComment];
	port->descfile		= values[ValueDescription];
	port->maintainer	= values[ValueMaintainer];
	port->categories	= values[ValueCategories];
	port->www		= values[ValueWWW];

	/*
	 * Split the following value to lists.
	 */
	field_list_fill(&port->edepends, values[ValueEDepends]);
	field_list_fill(&port->pdepends, values[ValuePDepends]);
	field_list_fill(&port->fdepends, values[ValueFDepends]);
	field_list_fill(&port->bdepends, values[ValueBDepends]);
	field_list_fill(&port->rdepends, values[ValueRDepends]);

	free(values[ValueEDepends]);
	free(values[ValuePDepends]);
	free(values[ValueFDepends]);
	free(values[ValueBDepends]);
	free(values[ValueRDepends]);

	STAILQ_INSERT_TAIL(ports, port, link);
}

/*
 * Find a port in the list by it's full path.
 */
static Port *
ports_find(const Ports *ports, const char *path)
{
	Port *port;

	STAILQ_FOREACH(port, ports, link)
		if (strcmp(port->portpath, path) == 0)
			return port;

	errx(1, "could not find dependency %s", path);
}

/*
 * Read the file specified by path and fill the port list.
 */
static void
ports_read(Ports *ports, const char *path)
{
	FILE *fp;
	char *line;
	size_t length;

	if ((fp = fopen(path, "r")) == NULL)
		err(1, "open: %s", path);

	STAILQ_INIT(ports);
	while ((line = fgetln(fp, &length)) != NULL && !feof(fp)) {
		if (length <= 0)
			err(1, "empty line, aborting");

		line[length - 1] = '\0';
		ports_add(ports, line);
	}

	fclose(fp);
}

/*
 * Write the new index to the file specified by path.
 */
static void
ports_write(const Ports *ports, const char *path)
{
	FILE *fp;
	struct sbuf *sbuf;
	Port *port;

	if ((fp = fopen(path, "w")) == NULL)
		err(1, "open");

	sbuf = sbuf_new_auto();

	STAILQ_FOREACH(port, ports, link) {
		sbuf_printf(sbuf, "%s|%s|%s|%s|%s|%s|%s|", port->name, port->portpath,
		    port->prefix, port->comment, port->descfile, port->maintainer,
		    port->categories);

		buf_add_depends(sbuf, &port->bdepends, ports, true);
		buf_add_depends(sbuf, &port->rdepends, ports, true);

		/* www is between dependencies */
		sbuf_printf(sbuf, "%s|", port->www);

		buf_add_depends(sbuf, &port->edepends, ports, true);
		buf_add_depends(sbuf, &port->pdepends, ports, true);
		buf_add_depends(sbuf, &port->fdepends, ports, false);

		/* Append that buffer */
		sbuf_finish(sbuf);
		fprintf(fp, "%s\n", sbuf_data(sbuf));
		sbuf_clear(sbuf);
	}

	fclose(fp);
	sbuf_delete(sbuf);
}

/*
 * Free the list of ports.
 */
static void
ports_free(Ports *ports)
{
	Port *port, *tmp;

	STAILQ_FOREACH_SAFE(port, ports, link, tmp) {
		free(port->name);
		free(port->portpath);
		free(port->prefix);
		free(port->comment);
		free(port->descfile);
		free(port->maintainer);
		free(port->categories);
		free(port->www);

		fields_list_free(&port->edepends);
		fields_list_free(&port->pdepends);
		fields_list_free(&port->fdepends);
		fields_list_free(&port->bdepends);
		fields_list_free(&port->rdepends);

		free(port);
	}
}

int
main(int argc, char **argv)
{
	Ports ports;

	if (argc < 3)
		usage();
		/* NOTREACHED */

	ports_read(&ports, argv[1]);
	ports_write(&ports, argv[2]);
	ports_free(&ports);

	return 0;
}
#include <stdio.h>

Changes to src/share/poudriere/awk/make_index.awk.

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
	as = "";

	for (a in A) {
		if (array_s(B, A[a]) != 0) {
			str = A[a];
			for (j in subst)
				sub(pat[j], subst[j], str);
				
			as = as" "str
			B[i] = A[a];
			i++;
		}
	}

	return as;
}







|








75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
	as = "";

	for (a in A) {
		if (array_s(B, A[a]) != 0) {
			str = A[a];
			for (j in subst)
				sub(pat[j], subst[j], str);

			as = as" "str
			B[i] = A[a];
			i++;
		}
	}

	return as;
}

Changes to src/share/poudriere/bulk.sh.

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
...
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
...
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

Options:
    -B name     -- What buildname to use (must be unique, defaults to YYYY-MM-DD_HH:MM:SS)
    -c          -- Clean all the previously built binary packages
    -C          -- Clean previously built packages from the given list to build
    -R          -- Clean RESTRICTED packages after building
    -t          -- Add some tests to the package build


    -s          -- Skip sanity checks
    -J n        -- Run n jobs in parallel (Default: to 8)
    -j name     -- Run only on the given jail

    -p tree     -- Specify on which ports tree the bulk build will be done
    -v          -- Be verbose; show more information. Use twice to enable debug output
    -w          -- Save WRKDIR on failed builds
    -z set      -- Specify which SET to use
    -a          -- Build the whole ports tree"

	exit 1
}

clean_restricted() {
	if [ -n "${NO_RESTRICTED}" ]; then
		msg "Cleaning restricted packages"

		# Remount rw
		# mount_nullfs does not support mount -u
		umount ${MASTERMNT}/packages
		mount_packages
		injail make -C /usr/ports -j ${PARALLEL_JOBS} clean-restricted
		# Remount ro
		umount ${MASTERMNT}/packages
		mount_packages -o ro










































	fi
}

SCRIPTPATH=`realpath $0`
SCRIPTPREFIX=`dirname ${SCRIPTPATH}`
PTNAME="default"
SKIPSANITY=0
SETNAME=""
CLEAN=0
CLEAN_LISTED=0
ALL=0

. ${SCRIPTPREFIX}/common.sh

[ $# -eq 0 ] && usage

while getopts "B:f:j:J:Ccn:p:Rtsvwz:a" FLAG; do
	case "${FLAG}" in
		B)
			BUILDNAME="${OPTARG}"
			;;
		t)
			export PORTTESTING=1
			export DEVELOPER_MODE=yes
			;;



		c)
			CLEAN=1
			;;
		C)
			CLEAN_LISTED=1
			;;
		f)
			LISTPKGS=${OPTARG}
			;;



		j)
			jail_exists ${OPTARG} || err 1 "No such jail: ${OPTARG}"
			JAILNAME=${OPTARG}
			;;
		J)
			PARALLEL_JOBS=${OPTARG}
			;;



		p)
			PTNAME=${OPTARG}
			;;
		R)
			NO_RESTRICTED=1
			;;
		s)
................................................................................
	rm -f ${LOGD}/*.log 2>/dev/null
fi

prepare_ports

bset status "building:"

if [ -z "${PORTTESTING}" -a -z "${ALLOW_MAKE_JOBS}" ]; then
	echo "DISABLE_MAKE_JOBS=yes" >> ${MASTERMNT}/etc/make.conf
fi

markfs prepkg ${MASTERMNT}

parallel_build ${JAILNAME} ${PTNAME} ${SETNAME} || : # Ignore errors as they are handled below

bset status "done:"

failed=$(bget ports.failed | awk '{print $1 ":" $3 }' | xargs echo)
built=$(bget ports.built | xargs echo)
ignored=$(bget ports.ignored | awk '{print $1}' | xargs echo)
skipped=$(bget ports.skipped | awk '{print $1}' | sort -u | xargs echo)
nbfailed=$(bget stats_failed)
nbignored=$(bget stats_ignored)
nbskipped=$(bget stats_skipped)
nbbuilt=$(bget stats_built)
[ "$nbfailed" = "-" ] && nbfailed=0
................................................................................
# Package all newly build ports
if [ $nbbuilt -eq 0 ]; then
	if [ $PKGNG -eq 1 ]; then
		msg "No package built, no need to update the repository"
	else
		msg "No package built, no need to update INDEX"
	fi
elif [ $PKGNG -eq 1 ]; then
	clean_restricted
	msg "Creating pkgng repository"
	bset status "pkgrepo:"
	tar xf ${MASTERMNT}/packages/Latest/pkg.txz -C ${MASTERMNT} \
		-s ",/.*/,poudriere/,g" "*/pkg-static"
	rm -f ${POUDRIERE_DATA}/packages/${MASTERNAME}/repo.txz ${POUDRIERE_DATA}/packages/${MASTERNAME}/repo.sqlite
	if [ -n "${PKG_REPO_SIGNING_KEY}" -a -f "${PKG_REPO_SIGNING_KEY}" ]; then
		${MASTERMNT}/poudriere/pkg-static repo ${POUDRIERE_DATA}/packages/${MASTERNAME}/ ${PKG_REPO_SIGNING_KEY}
	else
		${MASTERMNT}/poudriere/pkg-static repo ${POUDRIERE_DATA}/packages/${MASTERNAME}/
	fi
else
	clean_restricted
	msg "Preparing INDEX"
	bset status "index:"
	OSMAJ=`injail uname -r | awk -F. '{ print $1 }'`
	INDEXF=${POUDRIERE_DATA}/packages/${MASTERNAME}/INDEX-${OSMAJ}
	rm -f ${INDEXF}.1 2>/dev/null || :
	for pkg_file in ${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.tbz; do
		# Check for non-empty directory with no packages in it
		[ "${pkg}" = "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.tbz" ] && break
		msg_verbose "Extracting description for ${ORIGIN} ..."
		ORIGIN=$(pkg_get_origin ${pkg_file})
		[ -d ${MASTERMNT}/usr/ports/${ORIGIN} ] && injail make -C /usr/ports/${ORIGIN} describe >> ${INDEXF}.1
	done

	msg_n "Generating INDEX..."
	awk -v indf=${INDEXF}.1 -F\| -f ${AWKPREFIX}/make_index.awk ${INDEXF}.1 \
	    > ${INDEXF}
	echo " done"

	rm ${INDEXF}.1
	[ -f ${INDEXF}.bz2 ] && rm ${INDEXF}.bz2
	msg_n "Compressing INDEX-${OSMAJ}..."
	bzip2 -9 ${INDEXF}
	echo " done"

fi

cleanup
if [ $nbbuilt -gt 0 ]; then
	msg_n "Built ports: "
	echo ${built}
	echo ""







>
>



>










<
|
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>




|








>
>
>









>
>
>







>
>
>







 







|

<








|







 







<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>







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
...
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
...
252
253
254
255
256
257
258









259



260























261
262
263
264
265
266
267
268

Options:
    -B name     -- What buildname to use (must be unique, defaults to YYYY-MM-DD_HH:MM:SS)
    -c          -- Clean all the previously built binary packages
    -C          -- Clean previously built packages from the given list to build
    -R          -- Clean RESTRICTED packages after building
    -t          -- Add some tests to the package build
    -T          -- Try to build broken ports anyway
    -F          -- Only fetch from orignial master_site (skip FreeBSD mirrors)
    -s          -- Skip sanity checks
    -J n        -- Run n jobs in parallel (Default: to 8)
    -j name     -- Run only on the given jail
    -N          -- Do not build package repository or INDEX when build completed
    -p tree     -- Specify on which ports tree the bulk build will be done
    -v          -- Be verbose; show more information. Use twice to enable debug output
    -w          -- Save WRKDIR on failed builds
    -z set      -- Specify which SET to use
    -a          -- Build the whole ports tree"

	exit 1
}

clean_restricted() {

	msg "Cleaning restricted packages"
	bset status "clean_restricted:"
	# Remount rw
	# mount_nullfs does not support mount -u
	umount ${MASTERMNT}/packages
	mount_packages
	injail make -C /usr/ports -j ${PARALLEL_JOBS} clean-restricted >/dev/null
	# Remount ro
	umount ${MASTERMNT}/packages
	mount_packages -o ro
}

build_repo() {
	if [ $PKGNG -eq 1 ]; then
		msg "Creating pkgng repository"
		bset status "pkgrepo:"
		tar xf ${MASTERMNT}/packages/Latest/pkg.txz -C ${MASTERMNT} \
			-s ",/.*/,poudriere/,g" "*/pkg-static"
		rm -f ${POUDRIERE_DATA}/packages/${MASTERNAME}/repo.txz \
			${POUDRIERE_DATA}/packages/${MASTERNAME}/repo.sqlite
		if [ -n "${PKG_REPO_SIGNING_KEY}" -a \
			-f "${PKG_REPO_SIGNING_KEY}" ]; then
			${MASTERMNT}/poudriere/pkg-static repo \
				${POUDRIERE_DATA}/packages/${MASTERNAME}/ ${PKG_REPO_SIGNING_KEY}
		else
			${MASTERMNT}/poudriere/pkg-static repo \
				${POUDRIERE_DATA}/packages/${MASTERNAME}/
		fi
	else
		msg "Preparing INDEX"
		bset status "index:"
		OSMAJ=`injail uname -r | awk -F. '{ print $1 }'`
		INDEXF=${POUDRIERE_DATA}/packages/${MASTERNAME}/INDEX-${OSMAJ}
		rm -f ${INDEXF}.1 2>/dev/null || :
		for pkg_file in ${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.tbz; do
			# Check for non-empty directory with no packages in it
			[ "${pkg}" = "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.tbz" ] && break
			msg_verbose "Extracting description for ${ORIGIN} ..."
			ORIGIN=$(pkg_get_origin ${pkg_file})
			[ -d ${MASTERMNT}/usr/ports/${ORIGIN} ] &&
				injail make -C /usr/ports/${ORIGIN} describe >> ${INDEXF}.1
		done

		msg_n "Generating INDEX..."
		make_index ${INDEXF}.1 ${INDEXF}
		echo " done"

		rm ${INDEXF}.1
		[ -f ${INDEXF}.bz2 ] && rm ${INDEXF}.bz2
		msg_n "Compressing INDEX-${OSMAJ}..."
		bzip2 -9 ${INDEXF}
		echo " done"
	fi
}

SCRIPTPATH=`realpath $0`
SCRIPTPREFIX=`dirname ${SCRIPTPATH}`
PTNAME="default"
SKIPSANITY=0
SETNAME=""
CLEAN=0
CLEAN_LISTED=0
ALL=0
BUILD_REPO=1
. ${SCRIPTPREFIX}/common.sh

[ $# -eq 0 ] && usage

while getopts "B:f:j:J:CcNp:RFtTsvwz:a" FLAG; do
	case "${FLAG}" in
		B)
			BUILDNAME="${OPTARG}"
			;;
		t)
			export PORTTESTING=1
			export DEVELOPER_MODE=yes
			;;
		T)
			export TRYBROKEN=yes
			;;
		c)
			CLEAN=1
			;;
		C)
			CLEAN_LISTED=1
			;;
		f)
			LISTPKGS=${OPTARG}
			;;
		F)
			export MASTER_SITE_BACKUP=''
			;;
		j)
			jail_exists ${OPTARG} || err 1 "No such jail: ${OPTARG}"
			JAILNAME=${OPTARG}
			;;
		J)
			PARALLEL_JOBS=${OPTARG}
			;;
		N)
			BUILD_REPO=0
			;;
		p)
			PTNAME=${OPTARG}
			;;
		R)
			NO_RESTRICTED=1
			;;
		s)
................................................................................
	rm -f ${LOGD}/*.log 2>/dev/null
fi

prepare_ports

bset status "building:"

[ -z "${PORTTESTING}" -a -z "${ALLOW_MAKE_JOBS}" ] &&
	echo "DISABLE_MAKE_JOBS=yes" >> ${MASTERMNT}/etc/make.conf


markfs prepkg ${MASTERMNT}

parallel_build ${JAILNAME} ${PTNAME} ${SETNAME} || : # Ignore errors as they are handled below

bset status "done:"

failed=$(bget ports.failed | awk '{print $1 ":" $3 }' | xargs echo)
built=$(bget ports.built | awk '{print $1}' | xargs echo)
ignored=$(bget ports.ignored | awk '{print $1}' | xargs echo)
skipped=$(bget ports.skipped | awk '{print $1}' | sort -u | xargs echo)
nbfailed=$(bget stats_failed)
nbignored=$(bget stats_ignored)
nbskipped=$(bget stats_skipped)
nbbuilt=$(bget stats_built)
[ "$nbfailed" = "-" ] && nbfailed=0
................................................................................
# Package all newly build ports
if [ $nbbuilt -eq 0 ]; then
	if [ $PKGNG -eq 1 ]; then
		msg "No package built, no need to update the repository"
	else
		msg "No package built, no need to update INDEX"
	fi









else



	[ -n "${NO_RESTRICTED}" ] && clean_restricted























	[ ${BUILD_REPO} -eq 1 ] && build_repo
fi

cleanup
if [ $nbbuilt -gt 0 ]; then
	msg_n "Built ports: "
	echo ${built}
	echo ""

Changes to src/share/poudriere/common.sh.

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
...
104
105
106
107
108
109
110







111
112
113
114
115
116
117
...
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
...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
...
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
...
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
...
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472


473
474
475
476
477
478
479
...
548
549
550
551
552
553
554

555
556
557
558
559
560
561
...
641
642
643
644
645
646
647
648
649
650
651
652


653
654
655
656
657
658
659
...
660
661
662
663
664
665
666
667
668
669
670

671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
...
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715

716
717





718
719
720
721


722
723
724
725
726
727
728
...
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
...
852
853
854
855
856
857
858



859
860
861
862
863
864
865
...
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
...
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995





















996
997
998
999
1000
1001



1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
....
1022
1023
1024
1025
1026
1027
1028


1029







1030




1031

1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049

1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
....
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127




1128
1129
1130
1131
1132
1133
1134
....
1152
1153
1154
1155
1156
1157
1158


1159
1160




1161




1162
1163
1164
1165
1166
1167
1168
....
1173
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184
1185
1186
1187
....
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
....
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
....
1367
1368
1369
1370
1371
1372
1373
1374

1375
1376
1377
1378
1379
1380
1381
....
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
....
1478
1479
1480
1481
1482
1483
1484

1485
1486
1487
1488
1489
1490
1491
....
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582


1583
1584
1585
1586
1587
1588
1589
....
1592
1593
1594
1595
1596
1597
1598

1599
1600



1601
1602
1603
1604
1605
1606
1607
....
1672
1673
1674
1675
1676
1677
1678

1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689





















1690
1691
1692
1693
1694
1695
1696
1697
1698

1699

1700
1701

1702
1703
1704
1705
1706
1707
1708
....
1716
1717
1718
1719
1720
1721
1722

1723
1724
1725
1726
1727
1728
1729
....
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778


1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
....
1801
1802
1803
1804
1805
1806
1807













1808
1809
1810
1811

1812
1813
1814
1815
1816
1817
1818
....
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
....
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
....
1877
1878
1879
1880
1881
1882
1883

1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
....
1918
1919
1920
1921
1922
1923
1924

1925
1926

1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
....
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
....
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
....
2080
2081
2082
2083
2084
2085
2086
2087

2088
2089
2090
2091
2092
2093
2094
....
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143

2144





2145
2146
2147
2148
2149
2150
2151
....
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
....
2216
2217
2218
2219
2220
2221
2222

2223

2224
2225

2226
2227


2228
2229
2230

2231
2232
2233
2234
2235
2236
2237
2238
....
2297
2298
2299
2300
2301
2302
2303

2304
2305
2306
2307
2308
2309
2310

# zfs namespace
NS="poudriere"
IPS="$(sysctl -n kern.features.inet 2>/dev/null || echo 0)$(sysctl -n kern.features.inet6 2>/dev/null || echo 0)"
RELDATE=$(sysctl -n kern.osreldate)
JAILED=$(sysctl -n security.jail.jailed)

dir_empty() {
	find $1 -maxdepth 0 -empty
}

err() {
	export CRASHED=1
	if [ $# -ne 2 ]; then
		err 1 "err expects 2 arguments: exit_number \"message\""
	fi
	# Try to set status so other processes know this crashed
	bset status "crashed:" 2>/dev/null || :
................................................................................
eargs() {
	case $# in
	0) err 1 "No arguments expected" ;;
	1) err 1 "1 argument expected: $1" ;;
	*) err 1 "$# arguments expected: $*" ;;
	esac
}








log_start() {
	local logfile=$1

	# Make sure directory exists
	mkdir -p ${logfile%/*}

................................................................................
log_path() {
	echo "${POUDRIERE_DATA}/logs/${POUDRIERE_BUILD_TYPE}/${MASTERNAME}/${BUILDNAME}"
}

buildlog_start() {
	local portdir=$1
	local mnt=$(my_path)


	echo "build started at $(date)"
	echo "port directory: ${portdir}"
	echo "building for: $(injail uname -a)"
	echo "maintained by: $(injail make -C ${portdir} maintainer)"
	echo "Makefile ident: $(ident ${mnt}/${portdir}/Makefile|sed -n '2,2p')"
	echo "Poudriere version: ${POUDRIERE_VERSION}"
	echo ""
	echo "--SUB_LIST--"
	echo "$(injail env ${PORT_FLAGS} make -C ${portdir} -V SUB_LIST | tr ' ' '\n' | grep -v '^$')"
	echo "--End SUB_LIST--"
	echo ""
	echo "---Begin Environment---"
	injail env ${PKGENV} ${PORT_FLAGS}
	echo "---End Environment---"
	echo ""
	echo "---Begin make.conf---"
	cat ${mnt}/etc/make.conf
	echo "---End make.conf---"
	echo ""
	echo "---Begin OPTIONS List---"
	injail make -C ${portdir} showconfig
	echo "---End OPTIONS List---"














}

buildlog_stop() {
	local portdir=$1

	echo "build of ${portdir} ended at $(date)"
}
................................................................................

	[ -n ${CLEANUP_HOOK} ] && ${CLEANUP_HOOK}
}

show_log_info() {
	local log=$(log_path)
	msg "Logs: ${log}"
	[ -z "${URL_BASE}" ] || \
		msg "WWW: ${URL_BASE}/${POUDRIERE_BUILD_TYPE}/${MASTERNAME}/${BUILDNAME}"
}

siginfo_handler() {
	if [ "${POUDRIERE_BUILD_TYPE}" != "bulk" ]; then
		return 0;
	fi
	trappedinfo=1
	local status=$(bget status)
	local nbb=$(bget stats_built 2>/dev/null)
	local nbf=$(bget stats_failed 2>/dev/null)
	local nbi=$(bget stats_ignored 2>/dev/null)
	local nbs=$(bget stats_skipped 2>/dev/null)
	local nbq=$(bget stats_queued 2>/dev/null)
................................................................................
			status=$(bget ${j} status 2>/dev/null || :)
			# Skip builders not started yet
			[ -z "${status}" ] && continue
			# Hide idle workers
			[ "${status}" = "idle:" ] && continue
			origin=${status#*:}
			phase="${status%:*}"
			if [ "${origin}" != "${status}" ]; then
				pkgname=$(cache_get_pkgname ${origin})
				# Find the buildtime for this pkgname
				for pkgname_buildtime in $pkgname_buildtimes; do
					[ "${pkgname_buildtime%!*}" = "${pkgname}" ] || continue
					buildtime="${pkgname_buildtime#*!}"
					break
				done
................................................................................
		return
	fi

	if [ -z "${NO_ZFS}" ]; then
		data=$(zfs list -rt filesystem -H -o ${NS}:type,mountpoint ${ZPOOL}${ZROOTFS} | awk '$1 == "data" { print $2 }' | head -n 1)
		if [ -n "${data}" ]; then
			echo $data
		return
		fi
		zfs create -p -o ${NS}:type=data \
			-o mountpoint=${BASEFS}/data \
			${ZPOOL}${ZROOTFS}/data
	else
		mkdir -p "${BASEFS}/data"
	fi
................................................................................
	name=$1
	mnt=$(echo $2 | sed -e "s,//,/,g")
	fs=$3

	if [ -n "${fs}" -a "${fs}" != "none" ]; then
		msg_n "Creating ${name} fs..."
		zfs create -p \
			-o mountpoint=${mnt} ${fs} || err 1 " Fail" && echo " done"

	else
		mkdir -p ${mnt}
	fi
}

rollbackfs() {
	[ $# -ne 2 ] && eargs name mnt
................................................................................
}

umountfs() {
	[ $# -lt 1 ] && eargs mnt childonly
	local mnt=$1
	local childonly=$2
	local pattern
	
	[ -n "${childonly}" ] && pattern="/"

	[ -d "${mnt}" ] || return 0
	mnt=$(realpath ${mnt})
	mount | sort -r -k 2 | while read dev on pt opts; do
		case ${pt} in
		${mnt}${pattern}*)
			umount -f ${pt} || :
			if [ "${dev#/dev/md*}" != "${dev}" ]; then
				mdconfig -d -u ${dev#/dev/md*}
			fi
		;;
		esac
	done


}

zfs_getfs() {
	[ $# -ne 1 ] && eargs mnt
	local mnt=$(realpath $1)
	mount -t zfs | awk -v n="${mnt}" ' $3 == n { print $1 }'
}
................................................................................
./etc/group
./etc/make.conf
./etc/make.conf.bak
./etc/passwd
./etc/master.passwd
./etc/shells
./var/mail/*

EOF
	fi
	mtree -X ${mnt}/poudriere/mtree.${name}exclude \
		-xcn -k uid,gid,mode,size \
		-p ${mnt} > ${mnt}/poudriere/mtree.${name}
}

................................................................................
	for p in ${devfspath} ; do
		devfs -m ${mnt}/dev/ rule apply path "${p}" unhide
	done
	if [ "${mnt##*/}" != "ref" ]; then
		[ ${JAILED} -eq 0 ] && mount -t fdescfs fdesc ${mnt}/dev/fd
		mount -t procfs proc ${mnt}/proc
		if [ -z "${NOLINUX}" ]; then
			if [ "${arch}" = "i386" -o "${arch}" = "amd64" ]; then
				mount -t linprocfs linprocfs ${mnt}/compat/linux/proc
			fi
		fi
	fi


}

use_options() {
	[ $# -ne 2 ] && eargs mnt optionsdir
	local mnt=$1
	local optionsdir=$2

................................................................................
	if [ "${optionsdir}" = "-" ]; then
		optionsdir="${POUDRIERED}/options"
	else
		optionsdir="${POUDRIERED}/${optionsdir}-options"
	fi
	[ -d "${optionsdir}" ] || return 1
	optionsdir=$(realpath ${optionsdir} 2>/dev/null)
	if [ "${mnt##*/}" = "ref" ]; then
		msg "Mounting /var/db/ports from: ${optionsdir}"
	fi
	mount -t nullfs -o ro ${optionsdir} ${mnt}/var/db/ports || err 1 "Failed to mount OPTIONS directory"


	return 0
}

mount_packages() {
	local mnt=$(my_path)
	mount -t nullfs "$@" ${POUDRIERE_DATA}/packages/${MASTERNAME} \
		${mnt}/packages || \
		err 1 "Failed to mount the packages directory "
}

do_portbuild_mounts() {
	[ $# -lt 3 ] && eargs mnt jname ptname setname
	local mnt=$1
	local jname=$2
................................................................................

	[ -d ${portsdir}/ports ] && portsdir=${portsdir}/ports

	[ "$(realpath ${DISTFILES_CACHE})" != \
		"$(realpath -q ${portsdir}/distfiles)" ] || err 1 \
		"DISTFILES_CACHE cannot be in the portsdir as the portsdir will be mounted read-only"

	optionsdir="${MASTERNAME}"
	[ -n "${setname}" ] && optionsdir="${optionsdir} ${jname}-${setname}"
	optionsdir="${optionsdir} ${jname}-${ptname} ${jname} -"
 
	mkdir -p ${POUDRIERE_DATA}/packages/${MASTERNAME}/All
	if [ -d "${CCACHE_DIR:-/nonexistent}" ]; then
		mount -t nullfs ${CCACHE_DIR} ${mnt}/ccache
	fi
	[ -n "${MFSSIZE}" ] && mdmfs -M -S -o async -s ${MFSSIZE} md ${mnt}/wrkdirs
	[ ${TMPFS_WRKDIR} -eq 1 ] && mount -t tmpfs tmpfs ${mnt}/wrkdirs
	# Only show mounting messages once, not for every builder
	if [ ${mnt##*/} = "ref" ]; then
		if [ -d "${CCACHE_DIR:-/nonexistent}" ]; then
			msg "Mounting ccache from: ${CCACHE_DIR}"
		fi
		msg "Mounting packages from: ${POUDRIERE_DATA}/packages/${MASTERNAME}"
	fi

	mount -t nullfs -o ro ${portsdir} ${mnt}/usr/ports || err 1 "Failed to mount the ports directory "

	mount_packages -o ro
	mount -t nullfs ${DISTFILES_CACHE} ${mnt}/distfiles || err 1 "Failed to mount the distfiles cache directory"






	for opt in ${optionsdir}; do
		use_options ${mnt} ${opt} && break || continue
	done


}

jail_start() {
	[ $# -lt 2 ] && eargs name ptname setname
	local name=$1
	local ptname=$2
	local setname=$3
................................................................................
		fi
	done
	jail_exists ${name} || err 1 "No such jail: ${name}"
	jail_runs ${MASTERNAME} && err 1 "jail already running: ${MASTERNAME}"
	export HOME=/root
	export USER=root
	export FORCE_PACKAGE=yes
	if [ -z "${NO_PACKAGE_BUILDING}" ]; then
		export PACKAGE_BUILDING=yes
	fi

	[ ${SET_STATUS_ON_START-1} -eq 1 ] && export STATUS=1
	msg_n "Creating the reference jail..."
	clonefs ${mnt} ${tomnt} clean
	echo " done"

	msg "Mounting system devices for ${MASTERNAME}"
................................................................................

	# If this is a builder, don't cleanup, the master will handle that.
	if [ -n "${MY_JOBID}" ]; then
		[ -n "${PKGNAME}" ] && clean_pool ${PKGNAME} 1 || :
		return 0
	fi




	# Only bother with this if using jails as this may be being ran
	# from queue.sh or daemon.sh, etc.
	if [ -n "${MASTERMNT}" -a -n "${MASTERNAME}" ]; then
		if [ -d ${MASTERMNT}/poudriere/var/run ]; then
			for pid in ${MASTERMNT}/poudriere/var/run/*.pid; do
				# Ensure there is a pidfile to read or break
				[ "${pid}" = "${MASTERMNT}/poudriere/var/run/*.pid" ] && break
................................................................................
	export CLEANED_UP=1
}

sanity_check_pkgs() {
	local ret=0
	local depfile
	[ ! -d ${POUDRIERE_DATA}/packages/${MASTERNAME}/All ] && return $ret
	[ -n "$(dir_empty ${POUDRIERE_DATA}/packages/${MASTERNAME}/All)" ] && return $ret
	for pkg in ${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.${PKG_EXT}; do
		# Check for non-empty directory with no packages in it
		[ "${pkg}" = "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.${PKG_EXT}" ] && break
		depfile=$(deps_file ${pkg})
		while read dep; do
			if [ ! -e "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/${dep}.${PKG_EXT}" ]; then
				ret=1
................................................................................
			break
		fi

		# Wait until it is done, but check on it every so often
		# This is done instead of a 'sleep' as it should recognize
		# the command has completed right away instead of waiting
		# on the 'sleep' to finish
		unset n; until trappedinfo=; read -t $read_timeout n <&7 || \
			[ -z "$trappedinfo" ]; do :; done
		if [ "${n}" = "done" ]; then
			wait $childpid || ret=1
			break
		fi
		# Not done, was a timeout, check the log time
	done

	exec 7<&-
	exec 7>&-

	return $ret
}






















# Build+test port and return on first failure
build_port() {
	[ $# -ne 1 ] && eargs portdir
	local portdir=$1
	local port=${portdir##/usr/ports/}



	local targets="check-config fetch checksum extract patch configure build run-depends install-mtree install package ${PORTTESTING:+deinstall}"
	local mnt=$(my_path)
	local log=$(log_path)
	local listfilecmd network sub dists
	local pkgname=$(cache_get_pkgname ${port})
	local hangstatus

	for phase in ${targets}; do
		bset ${MY_JOBID} status "${phase}:${port}"
		job_msg_verbose "Status for build ${port}: ${phase}"
		if [ "${phase}" = "fetch" ]; then
			jstop
................................................................................
			echo "${listfilecmd} | xargs ldd 2>&1 | awk '/=>/ { print $3 }' | sort -u" > ${mnt}/shared.sh
			injail sh /shared.sh
			rm -f ${mnt}/shared.sh
			;;
		esac

		print_phase_header ${phase}


		[ "${phase}" = "package" ] && echo "PACKAGES=/new_packages" >> ${mnt}/etc/make.conf












		# 24 hours for 1 command, or 20 minutes with no log update

		nohang 86400 1200 ${log}/logs/${pkgname}.log \
			injail env ${PKGENV} ${PORT_FLAGS} \
			make -C ${portdir} ${phase}
		hangstatus=$? # This is done as it may return 1 or 2 or 3
		if [ $hangstatus -ne 0 ]; then
			# 1 = cmd failed, not a timeout
			# 2 = log timed out
			# 3 = cmd timeout
			if [ $hangstatus -eq 2 ]; then
				msg "Killing runaway build"
				bset ${MY_JOBID} status "${phase}/runaway:${port}"
				job_msg_verbose "Status for build ${port}: runaway"
			elif [ $hangstatus -eq 3 ]; then
				msg "Killing timed out build"
				bset ${MY_JOBID} status "${phase}/timeout:${port}"
				job_msg_verbose "Status for build ${port}: timeout"
			fi
			return 1

		fi

		if [ "${phase}" = "checksum" ]; then
			jstop
			jstart 0
		fi
		print_phase_footer

		if [ "${phase}" = "checksum" ]; then
			sub=$(injail make -C ${portdir} -VDIST_SUBDIR)
			dists=$(injail make -C ${portdir} -V_DISTFILES -V_PATCHFILES)
			mkdir -p ${mnt}/portdistfiles
			echo "DISTDIR=/portdistfiles" >> ${mnt}/etc/make.conf
			for d in ${dists}; do
				[ -f ${DISTFILES_CACHE}/${sub}/${d} ] || continue
				echo ${DISTFILES_CACHE}/${sub}/${d}
			done | pax -rw -p p -s ",${DISTFILES_CACHE},,g" ${mnt}/portdistfiles
		fi

		if [ "${phase}" = "deinstall" ]; then
			msg "Checking for extra files and directories"
			PREFIX=$(injail env ${PORT_FLAGS} make -C ${portdir} -VPREFIX)
			bset ${MY_JOBID} status "leftovers:${port}"
			local portname datadir etcdir docsdir examplesdir wwwdir site_perl
			local add=$(mktemp ${mnt}/tmp/add.XXXXXX)
			local add1=$(mktemp ${mnt}/tmp/add1.XXXXXX)
			local del=$(mktemp ${mnt}/tmp/del.XXXXXX)
			local del1=$(mktemp ${mnt}/tmp/del1.XXXXXX)
			local mod=$(mktemp ${mnt}/tmp/mod.XXXXXX)
			local mod1=$(mktemp ${mnt}/tmp/mod1.XXXXXX)
			local die=0
................................................................................
				fi
				case $modtype in
				+)
					case "${ppath}" in
					*) echo "${ppath}" >> ${add} ;;
					esac
					;;
				-) 
					# Skip if it is PREFIX and non-LOCALBASE. See misc/kdehier4
					# or mail/qmail for examples
					[ "${ppath}" = "${PREFIX}" -a \
						"${LOCALBASE}" != "${PREFIX}" ] && ignore_path=1

					if [ $ignore_path -ne 0 ]; then
						echo "${ppath}" >> ${del}
					fi
					;;
				M)
					[ -d "${path}" ] && continue
					case "${ppath}" in
					# This is a cache file for gio modules could be modified for any gio modules
					lib/gio/modules/giomodule.cache) ;;
					# removal of info files leaves entry uneasy to cleanup in info/dir
					# accept a modification of this file
					info/dir) ;;
					# The is pear database cache
					%%PEARDIR%%/.depdb|%%PEARDIR%%/.filemap) ;;




					*) echo "${ppath}" >> ${mod} ;;
					esac
					;;
				esac
			done
			sort ${add} > ${add1}
			sort ${del} > ${del1}
................................................................................
				die=1
				cat ${mod1}
			fi
			rm -f ${add} ${add1} ${del} ${del1} ${mod} ${mod1}
			[ $die -eq 0 ] || return 1
		fi
	done


	# everything was fine we can copy package the package to the package
	# directory




	pax -rw -p p -s ",${mnt}/new_packages,,g" ${mnt}/new_packages ${POUDRIERE_DATA}/packages/${MASTERNAME}





	bset ${MY_JOBID} status "idle:"
	return 0
}

# Save wrkdir and return path to file
save_wrkdir() {
................................................................................
	local phase="$4"
	local tardir=${POUDRIERE_DATA}/wrkdirs/${MASTERNAME}/${PTNAME}
	local tarname=${tardir}/${PKGNAME}.${WRKDIR_ARCHIVE_FORMAT}
	local mnted_portdir=${mnt}/wrkdirs/${portdir}

	[ -n "${SAVE_WRKDIR}" ] || return 0
	# Only save if not in fetch/checksum phase
	[ "${failed_phase}" != "fetch" -a "${failed_phase}" != "checksum" -a "${failed_phase}" != "extract" ] || return 0


	mkdir -p ${tardir}

	# Tar up the WRKDIR, and ignore errors
	case ${WRKDIR_ARCHIVE_FORMAT} in
	tar) COMPRESSKEY="" ;;
	tgz) COMPRESSKEY="z" ;;
................................................................................
	err 1 "Unknown stuck queue bug detected. Give this information to poudriere developers:
$(find ${mnt}/poudriere/building ${mnt}/poudriere/pool ${mnt}/poudriere/deps)"
}

queue_empty() {
	local pool_dir
	local mnt=$(my_path)
	[ -n "$(dir_empty ${mnt}/poudriere/deps)" ] || return 1

	for pool_dir in ${POOL_BUCKET_DIRS}; do
		[ -n "$(dir_empty ${pool_dir})" ] || return 1
	done

	return 0
}

mark_done() {
	[ $# -eq 1 ] || eargs pkgname
................................................................................
	msg "Hit CTRL+t at any time to see build progress and stats"

	while :; do
		builders_active=0
		for j in ${JOBS}; do
			name="${MASTERNAME}-job-${j}"
			if [ -f  "${mnt}/poudriere/var/run/${j}.pid" ]; then
				if pgrep -F "${mnt}/poudriere/var/run/${j}.pid" >/dev/null 2>&1; then
					builders_active=1
					continue
				fi
				read pkgname < ${mnt}/poudriere/var/run/${j}.pkgname
				rm -f ${mnt}/poudriere/var/run/${j}.pid \
					${mnt}/poudriere/var/run/${j}.pkgname
				bset ${j} status "idle:"
................................................................................
				# All work is done
				break
			fi
		fi

		[ ${builders_active} -eq 1 ] || deadlock_detected

		unset jobid; until trappedinfo=; read -t 30 jobid <&6 || [ -z "$trappedinfo" ]; do :; done

	done
	exec 6<&-
	exec 6>&-
}

start_html_json() {
	json_main &
................................................................................
	local nbi=$(bget stats_ignored)
	local nbs=$(bget stats_skipped)
	local ndone=$((nbb + nbf + nbi + nbs))
	local nremaining=$((nbq - ndone))
	local real_parallel_jobs=${PARALLEL_JOBS}

	# If pool is empty, just return
	test ${nremaining} -eq 0 && return 0

	# Minimize PARALLEL_JOBS to queue size
	if [ ${PARALLEL_JOBS} -gt ${nremaining} ]; then
		PARALLEL_JOBS=${nremaining##* }
	fi

	msg "Building ${nremaining} packages using ${PARALLEL_JOBS} builders"
	JOBS="$(jot -w %02d ${PARALLEL_JOBS})"

	start_html_json

	bset status "starting_jobs:"
................................................................................
	[ ${clean_rdepends} -eq 1 ] && port=$(cache_get_origin "${pkgname}")

	# Cleaning queue (pool is cleaned here)
	sh ${SCRIPTPREFIX}/clean.sh "${MASTERMNT}" "${pkgname}" ${clean_rdepends} | sort -u | while read skipped_pkgname; do
		skipped_origin=$(cache_get_origin "${skipped_pkgname}")
		badd ports.skipped "${skipped_origin} ${skipped_pkgname} ${pkgname}"
		job_msg "Skipping build of ${skipped_origin}: Dependent port ${port} failed"

	done

	balance_pool
}

print_phase_header() {
	printf "=======================<phase: %-13s>==========================\n" "$1"
................................................................................
	buildlog_start ${portdir}

	if [ -n "${ignore}" ]; then
		msg "Ignoring ${port}: ${ignore}"
		badd ports.ignored "${port} ${PKGNAME} ${ignore}"
		job_msg "Finished build of ${port}: Ignored: ${ignore}"
		clean_rdepends=1
	else
		bset ${MY_JOBID} status "depends:${port}"
		job_msg_verbose "Status for build ${port}: depends"
		print_phase_header "depends"
		if ! injail make -C ${portdir} pkg-depends fetch-depends extract-depends \
			patch-depends build-depends lib-depends; then
			build_failed=1
			failed_phase="depends"
		else
			print_phase_footer
			# Only build if the depends built fine
			injail make -C ${portdir} clean
			if ! build_port ${portdir}; then
				build_failed=1
				failed_status=$(bget ${MY_JOBID} status)
				failed_phase=${failed_status%:*}

				save_wrkdir ${mnt} "${port}" "${portdir}" "${failed_phase}" || :
			elif [ -f ${mnt}/${portdir}/.keep ]; then
				save_wrkdir ${mnt} "${port}" "${portdir}" "noneed" ||:
			fi

			injail make -C ${portdir} clean
		fi

		if [ ${build_failed} -eq 0 ]; then
			badd ports.built "${port} ${PKGNAME}"
			job_msg "Finished build of ${port}: Success"

			# Cache information for next run
			pkg_cache_data "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/${PKGNAME}.${PKG_EXT}" ${port} || :
		else
			# Symlink the buildlog into errors/
			ln -s ../${PKGNAME}.log ${log}/logs/errors/${PKGNAME}.log
			badd ports.failed "${port} ${PKGNAME} ${failed_phase}"
			job_msg "Finished build of ${port}: Failed: ${failed_phase}"


			clean_rdepends=1
		fi
	fi

	clean_pool ${PKGNAME} ${clean_rdepends}

	bset ${MY_JOBID} status "done:${port}"
................................................................................

	echo ${MY_JOBID} >&6
}

stop_build() {
	[ $# -eq 2 ] || eargs portdir logfile
	local portdir="$1"

	local logfile="$2"




	# 2 = HEADER+ps itself
	if [ $(injail ps aux | wc -l) -ne 2 ]; then
		msg "Leftover processes:"
		injail ps auxwwd | grep -v 'ps auxwwd'
	fi
	# Always kill to avoid missing anything
	injail kill -9 -1 2>/dev/null || :
................................................................................
	local pkg=$1
	local originfile=$(pkg_cache_dir ${pkg})/origin
	local origin=$2

	if [ ! -f "${originfile}" ]; then
		if [ -z "${origin}" ]; then
			if [ "${PKG_EXT}" = "tbz" ]; then

				origin=$(tar -xf "${pkg}" -O +CONTENTS | awk -F: '$1 == "@comment ORIGIN" { print $2 }')
			else
				origin=$(pkg query -F "${pkg}" "%o")
			fi
		fi
		echo ${origin} > "${originfile}"
	else
		read origin < "${originfile}"
	fi
	echo ${origin}
}






















pkg_get_options() {
	[ $# -ne 1 ] && eargs pkg
	local pkg=$1
	local optionsfile=$(pkg_cache_dir ${pkg})/options
	local compiled_options

	if [ ! -f "${optionsfile}" ]; then
		if [ "${PKG_EXT}" = "tbz" ]; then

			compiled_options=$(tar -xf "${pkg}" -O +CONTENTS | awk -F: '$1 == "@comment OPTIONS" {print $2}' | tr ' ' '\n' | sed -n 's/^\+\(.*\)/\1/p' | sort | tr '\n' ' ')

		else
			compiled_options=$(pkg query -F "${pkg}" '%Ov %Ok' | awk '$1 == "on" {print $2}' | sort | tr '\n' ' ')

		fi
		echo "${compiled_options}" > "${optionsfile}"
		echo "${compiled_options}"
		return 0
	fi
	# optionsfile is multi-line, no point for read< trick here
	cat "${optionsfile}"
................................................................................
	local origin=$2
	local cachedir=$(pkg_cache_dir ${pkg})
	local originfile=${cachedir}/origin

	mkdir -p $(pkg_cache_dir ${pkg})
	pkg_get_options ${pkg} > /dev/null
	pkg_get_origin ${pkg} ${origin} > /dev/null

	deps_file ${pkg} > /dev/null
	set -e
}

pkg_to_pkgname() {
	[ $# -ne 1 ] && eargs pkg
	local pkg=$1
................................................................................
}

# Deleted cached information for stale packages (manually removed)
delete_stale_pkg_cache() {
	local pkgname
	local cachedir=$(cache_dir)
	[ ! -d ${cachedir} ] && return 0
	[ -n "$(dir_empty ${cachedir})" ] && return 0
	for pkg in ${cachedir}/*.${PKG_EXT}; do
		pkg_file=${pkg##*/}
		# If this package no longer exists in the PKGDIR, delete the cache.
		if [ ! -e "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/${pkg_file}" ]; then
			clear_pkg_cache ${pkg}
		fi
	done


}

delete_old_pkg() {
	local pkg="$1"
	local mnt=$(my_path)
	local o v v2 compiled_options current_options
	if [ "${pkg##*/}" = "repo.txz" ]; then
		msg "Removing invalid pkg repo file: ${pkg}"
		rm -f ${pkg}
		return 0
	fi

	mkdir -p $(pkg_cache_dir ${pkg})
................................................................................
	v2=$(cache_get_pkgname ${o})
	v2=${v2##*-}
	if [ "$v" != "$v2" ]; then
		msg "Deleting old version: ${pkg##*/}"
		delete_pkg ${pkg}
		return 0
	fi














	# Check if the compiled options match the current options from make.conf and /var/db/options
	if [ "${CHECK_CHANGED_OPTIONS:-no}" != "no" ]; then
		current_options=$(injail make -C /usr/ports/${o} pretty-print-config | tr ' ' '\n' | sed -n 's/^\+\(.*\)/\1/p' | sort | tr '\n' ' ')

		compiled_options=$(pkg_get_options ${pkg})

		if [ "${compiled_options}" != "${current_options}" ]; then
			msg "Options changed, deleting: ${pkg##*/}"
			if [ "${CHECK_CHANGED_OPTIONS}" = "verbose" ]; then
				msg "Pkg: ${compiled_options}"
				msg "New: ${current_options}"
................................................................................
			return 0
		fi
	fi
}

delete_old_pkgs() {
	[ ! -d ${POUDRIERE_DATA}/packages/${MASTERNAME}/All ] && return 0
	[ -n "$(dir_empty ${POUDRIERE_DATA}/packages/${MASTERNAME}/All)" ] && return 0
	parallel_start
	for pkg in ${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.${PKG_EXT}; do
		# Check for non-empty directory with no packages in it
		[ "${pkg}" = "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.${PKG_EXT}" ] && break
		parallel_run delete_old_pkg "${pkg}"
	done
	parallel_stop
................................................................................
}

lock_acquire() {
	[ $# -ne 1 ] && eargs lockname
	local lockname=$1

	while :; do
		if mkdir ${POUDRIERE_DATA}/.lock-${MASTERNAME}-${lockname} 2>/dev/null; then
			break
		fi
		sleep 0.1
	done
}

lock_release() {
	[ $# -ne 1 ] && eargs lockname
	local lockname=$1
................................................................................
	local cache_origin_pkgname=${MASTERMNT}/poudriere/var/cache/origin-pkgname/${origin%%/*}_${origin##*/}
	local cache_pkgname_origin

	[ -f ${cache_origin_pkgname} ] && read pkgname < ${cache_origin_pkgname}

	# Add to cache if not found.
	if [ -z "${pkgname}" ]; then

		[ -d "${MASTERMNT}/usr/ports/${origin}" ] || err 1 "Invalid port origin '${origin}' not found."
		pkgname=$(injail make -C /usr/ports/${origin} -VPKGNAME || \
			err 1 "Error getting PKGNAME for ${origin}")
		# Make sure this origin did not already exist
		existing_origin=$(cache_get_origin "${pkgname}" 2>/dev/null || :)
		# It may already exist due to race conditions, it is not harmful. Just ignore.
		if [ "${existing_origin}" != "${origin}" ]; then
			[ -n "${existing_origin}" ] && \
				err 1 "Duplicated origin for ${pkgname}: ${origin} AND ${existing_origin}. Rerun with -vv to see which ports are depending on these."
			echo "${pkgname}" > ${cache_origin_pkgname}
			cache_pkgname_origin="${MASTERMNT}/poudriere/var/cache/pkgname-origin/${pkgname}"
			echo "${origin}" > "${cache_pkgname_origin}"
		fi
	fi

................................................................................
	local pkg_pooldir="${mnt}/poudriere/deps/${pkgname}"
	mkdir "${pkg_pooldir}" 2>/dev/null || return 0

	msg_verbose "Computing deps for ${port}"

	for dep_port in `list_deps ${port}`; do
		msg_debug "${port} depends on ${dep_port}"

		[ "${port}" != "${dep_port}" ] || err 1 "${port} incorrectly depends on itself. Please contact maintainer of the port to fix this."
		# Detect bad cat/origin/ dependency which pkgng will not register properly

		[ "${dep_port}" = "${dep_port%/}" ] || err 1 "${port} depends on bad origin '${dep_port}'; Please contact maintainer of the port to fix this."
		dep_pkgname=$(cache_get_pkgname ${dep_port})

		# Only do this if it's not already done, and not ALL, as everything will
		# be touched anyway
		[ ${ALL:-0} -eq 0 ] && ! [ -d "${mnt}/poudriere/deps/${dep_pkgname}" ] && \
			compute_deps "${dep_port}" "${dep_pkgname}"

		touch "${pkg_pooldir}/${dep_pkgname}"
		mkdir -p "${mnt}/poudriere/rdeps/${dep_pkgname}"
		ln -sf "${pkg_pooldir}/${dep_pkgname}" \
			"${mnt}/poudriere/rdeps/${dep_pkgname}/${pkgname}"
	done
................................................................................
}

listed_ports() {
	if [ ${ALL:-0} -eq 1 ]; then
		PORTSDIR=$(pget ${PTNAME} mnt)
		[ -d "${PORTSDIR}/ports" ] && PORTSDIR="${PORTSDIR}/ports"
		for cat in $(awk '$1 == "SUBDIR" { print $3}' ${PORTSDIR}/Makefile); do
			awk -v cat=${cat}  '$1 == "SUBDIR" { print cat"/"$3}' ${PORTSDIR}/${cat}/Makefile
		done
		return 0
	fi
	if [ -z "${LISTPORTS}" ]; then
		if [ -n "${LISTPKGS}" ]; then
			grep -v -E '(^[[:space:]]*#|^[[:space:]]*$)' ${LISTPKGS}
		fi
	else
		echo ${LISTPORTS} | tr ' ' '\n'
	fi
}

parallel_exec() {
	local cmd="$1"
................................................................................
	local log=$(log_path)
	local n port pn nbq resuming_build

	msg "Calculating ports order and dependencies"
	mkdir -p "${MASTERMNT}/poudriere"
	[ ${TMPFS_DATA} -eq 1 ] && mount -t tmpfs tmpfs "${MASTERMNT}/poudriere"
	rm -rf "${MASTERMNT}/poudriere/var/cache/origin-pkgname" \
	       "${MASTERMNT}/poudriere/var/cache/pkgname-origin" 2>/dev/null || :
	mkdir -p "${MASTERMNT}/poudriere/building" \
		"${MASTERMNT}/poudriere/pool" \
		"${MASTERMNT}/poudriere/deps" \
		"${MASTERMNT}/poudriere/rdeps" \
		"${MASTERMNT}/poudriere/var/run" \
		"${MASTERMNT}/poudriere/var/cache" \
		"${MASTERMNT}/poudriere/var/cache/origin-pkgname" \
................................................................................
	mkdir -p ${log}/logs ${log}/logs/errors
	ln -sfh ${BUILDNAME} ${log%/*}/latest
	cp ${HTMLPREFIX}/* ${log}

	bset status "computingdeps:"
	parallel_start
	for port in $(listed_ports); do
		[ -d "${MASTERMNT}/usr/ports/${port}" ] || err 1 "Invalid port origin: ${port}"

		parallel_run compute_deps ${port}
	done
	parallel_stop

	bset status "sanity:"

	if [ ${CLEAN_LISTED:-0} -eq 1 ]; then
................................................................................
		msg "Sanity checking the repository"
		delete_stale_pkg_cache
		delete_old_pkgs

		while :; do
			sanity_check_pkgs && break
		done
	fi

	msg "Deleting stale symlinks"
	find -L ${POUDRIERE_DATA}/packages/${MASTERNAME} -type l -exec rm -f {} +







	bset status "cleaning:"
	msg "Cleaning the build queue"
	export LOCALBASE=${LOCALBASE:-/usr/local}
	for pn in $(ls ${MASTERMNT}/poudriere/deps/); do
		if [ -f "${MASTERMNT}/packages/All/${pn}.${PKG_EXT}" ]; then
			find_all_pool_references "${pn}"
		fi
................................................................................

balance_pool() {
	# Don't bother if disabled
	[ ${POOL_BUCKETS} -gt 0 ] || return 0

	local pkgname pkg_dir dep_count rdep lock

	[ -z "$(dir_empty ${MASTERMNT}/poudriere/pool/unbalanced)" ] || return 0
	# Avoid running this in parallel, no need
	lock=${MASTERMNT}/poudriere/.lock-balance_pool
	mkdir ${lock} 2>/dev/null || return 0

	if [ -n "${MY_JOBID}" ]; then
		bset ${MY_JOBID} status "balancing_pool:"
	else
................................................................................
	echo "#### ${makeconf} ####" >> ${mnt}/etc/make.conf
	cat "${makeconf}" >> ${mnt}/etc/make.conf
}

RESOLV_CONF=""
STATUS=0 # out of jail #


test -f ${SCRIPTPREFIX}/../../etc/poudriere.conf || err 1 "Unable to find ${SCRIPTPREFIX}/../../etc/poudriere.conf"

. ${SCRIPTPREFIX}/../../etc/poudriere.conf
POUDRIERED=${SCRIPTPREFIX}/../../etc/poudriere.d

AWKPREFIX=${SCRIPTPREFIX}/awk
HTMLPREFIX=${SCRIPTPREFIX}/html



# If the zfs module is not loaded it means we can't have zfs
[ -z "${NO_ZFS}" ] && lsvfs zfs >/dev/null 2>&1 || NO_ZFS=yes

[ -z "${NO_ZFS}" -a -z "$(zpool list -H -o name 2>/dev/null)" ] && NO_ZFS=yes

[ -z "${NO_ZFS}" -a -z ${ZPOOL} ] && err 1 "ZPOOL variable is not set"
[ -z ${BASEFS} ] && err 1 "Please provide a BASEFS variable in your poudriere.conf"

trap sig_handler SIGINT SIGTERM SIGKILL
trap exit_handler EXIT
trap siginfo_handler SIGINFO
................................................................................
			# Delete the old properties
			zfs inherit -r ${NS}:type ${fs}
			zfs inherit -r ${NS}:name ${fs}
			zfs inherit -r ${NS}:method ${fs}
		done
	if [ -f ${POUDRIERED}/portstrees ]; then
		while read name method mnt; do

			msg "Converting the ${name} ports tree"
			mkdir ${POUDRIERED}/ports/${name}
			echo ${method} > ${POUDRIERED}/ports/${name}/method
			echo ${mnt} > ${POUDRIERED}/ports/${name}/mnt
		done < ${POUDRIERED}/portstrees
		rm -f ${POUDRIERED}/portstrees
	fi







<
<
<
<







 







>
>
>
>
>
>
>







 







>








<
<
<
<




<
<
<
<



>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|




|
|
<







 







|







 







|







 







|
>







 







|








<
|
<



>
>







 







>







 







|

|
|
<
>
>







 







|

<
|
>







|







 







<
<
<
<

|

<




|

<



|
>

|
>
>
>
>
>




>
>







 







<
|
<







 







>
>
>







 







|







 







|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>
>
|


|
<







 







>
>
|
>
>
>
>
>
>
>

>
>
>
>
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>









<
<


<
<
<
|






<







 







|


|


|













>
>
>
>







 







>
>
|
|
>
>
>
>
|
>
>
>
>







 







|
>







 







|


|







 







|







 







|
>







 







|


|
<
<







 







>







 







|
<
<
<
<
<
<
<
|
<
<
|
|
|
|
|

|
|
|
|

|
<




>







>
>







 







>


>
>
>







 







>
|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
|
>

|
>







 







>







 







|



|

<

>
>





|







 







>
>
>
>
>
>
>
>
>
>
>
>
>



|
>







 







|







 







|

<







 







>
|
|





|







 







>
|

>
|




|







 







|




|

<







 







|







 







|
>







 







<

|
|
>

>
>
>
>
>







 







|







 







>
|
>


>


>
>



>
|







 







>







28
29
30
31
32
33
34




35
36
37
38
39
40
41
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
...
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
...
282
283
284
285
286
287
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
...
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
...
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

477

478
479
480
481
482
483
484
485
486
487
488
489
...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
...
652
653
654
655
656
657
658
659
660
661
662

663
664
665
666
667
668
669
670
671
...
672
673
674
675
676
677
678
679
680

681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
...
702
703
704
705
706
707
708




709
710
711

712
713
714
715
716
717

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
...
767
768
769
770
771
772
773

774

775
776
777
778
779
780
781
...
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
...
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
...
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044

1045
1046
1047
1048
1049
1050
1051
....
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111


1112
1113



1114
1115
1116
1117
1118
1119
1120

1121
1122
1123
1124
1125
1126
1127
....
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
....
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
....
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
....
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
....
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
....
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
....
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498


1499
1500
1501
1502
1503
1504
1505
....
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
....
1603
1604
1605
1606
1607
1608
1609
1610







1611


1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623

1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
....
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
....
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
....
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
....
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861

1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
....
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
....
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
....
1952
1953
1954
1955
1956
1957
1958
1959
1960

1961
1962
1963
1964
1965
1966
1967
....
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
....
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
....
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055

2056
2057
2058
2059
2060
2061
2062
....
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
....
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
....
2235
2236
2237
2238
2239
2240
2241

2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
....
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
....
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
....
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424

# zfs namespace
NS="poudriere"
IPS="$(sysctl -n kern.features.inet 2>/dev/null || echo 0)$(sysctl -n kern.features.inet6 2>/dev/null || echo 0)"
RELDATE=$(sysctl -n kern.osreldate)
JAILED=$(sysctl -n security.jail.jailed)





err() {
	export CRASHED=1
	if [ $# -ne 2 ]; then
		err 1 "err expects 2 arguments: exit_number \"message\""
	fi
	# Try to set status so other processes know this crashed
	bset status "crashed:" 2>/dev/null || :
................................................................................
eargs() {
	case $# in
	0) err 1 "No arguments expected" ;;
	1) err 1 "1 argument expected: $1" ;;
	*) err 1 "$# arguments expected: $*" ;;
	esac
}

run_hook() {
	local hookfile=${HOOKDIR}/${1}.sh
	shift
	[ -f ${hookfile} ] && /bin/sh ${hookfile} $@
	return 0
}

log_start() {
	local logfile=$1

	# Make sure directory exists
	mkdir -p ${logfile%/*}

................................................................................
log_path() {
	echo "${POUDRIERE_DATA}/logs/${POUDRIERE_BUILD_TYPE}/${MASTERNAME}/${BUILDNAME}"
}

buildlog_start() {
	local portdir=$1
	local mnt=$(my_path)
	local var

	echo "build started at $(date)"
	echo "port directory: ${portdir}"
	echo "building for: $(injail uname -a)"
	echo "maintained by: $(injail make -C ${portdir} maintainer)"
	echo "Makefile ident: $(ident ${mnt}/${portdir}/Makefile|sed -n '2,2p')"
	echo "Poudriere version: ${POUDRIERE_VERSION}"
	echo ""




	echo "---Begin Environment---"
	injail env ${PKGENV} ${PORT_FLAGS}
	echo "---End Environment---"
	echo ""




	echo "---Begin OPTIONS List---"
	injail make -C ${portdir} showconfig
	echo "---End OPTIONS List---"
	echo ""
	for var in CONFIGURE_ARGS CONFIGURE_ENV MAKE_ENV; do
		echo "--${var}--"
		echo "$(injail env ${PORT_FLAGS} make -C ${portdir} -V ${var})"
		echo "--End ${var}--"
		echo ""
	done
	echo "--SUB_LIST--"
	echo "$(injail env ${PORT_FLAGS} make -C ${portdir} -V SUB_LIST | tr ' ' '\n' | grep -v '^$')"
	echo "--End SUB_LIST--"
	echo ""
	echo "---Begin make.conf---"
	cat ${mnt}/etc/make.conf
	echo "---End make.conf---"
}

buildlog_stop() {
	local portdir=$1

	echo "build of ${portdir} ended at $(date)"
}
................................................................................

	[ -n ${CLEANUP_HOOK} ] && ${CLEANUP_HOOK}
}

show_log_info() {
	local log=$(log_path)
	msg "Logs: ${log}"
	[ -z "${URL_BASE}" ] ||
		msg "WWW: ${URL_BASE}/${POUDRIERE_BUILD_TYPE}/${MASTERNAME}/${BUILDNAME}"
}

siginfo_handler() {
	[ "${POUDRIERE_BUILD_TYPE}" != "bulk" ] && return 0


	trappedinfo=1
	local status=$(bget status)
	local nbb=$(bget stats_built 2>/dev/null)
	local nbf=$(bget stats_failed 2>/dev/null)
	local nbi=$(bget stats_ignored 2>/dev/null)
	local nbs=$(bget stats_skipped 2>/dev/null)
	local nbq=$(bget stats_queued 2>/dev/null)
................................................................................
			status=$(bget ${j} status 2>/dev/null || :)
			# Skip builders not started yet
			[ -z "${status}" ] && continue
			# Hide idle workers
			[ "${status}" = "idle:" ] && continue
			origin=${status#*:}
			phase="${status%:*}"
			if [ -n "${origin}" -a "${origin}" != "${status}" ]; then
				pkgname=$(cache_get_pkgname ${origin})
				# Find the buildtime for this pkgname
				for pkgname_buildtime in $pkgname_buildtimes; do
					[ "${pkgname_buildtime%!*}" = "${pkgname}" ] || continue
					buildtime="${pkgname_buildtime#*!}"
					break
				done
................................................................................
		return
	fi

	if [ -z "${NO_ZFS}" ]; then
		data=$(zfs list -rt filesystem -H -o ${NS}:type,mountpoint ${ZPOOL}${ZROOTFS} | awk '$1 == "data" { print $2 }' | head -n 1)
		if [ -n "${data}" ]; then
			echo $data
			return
		fi
		zfs create -p -o ${NS}:type=data \
			-o mountpoint=${BASEFS}/data \
			${ZPOOL}${ZROOTFS}/data
	else
		mkdir -p "${BASEFS}/data"
	fi
................................................................................
	name=$1
	mnt=$(echo $2 | sed -e "s,//,/,g")
	fs=$3

	if [ -n "${fs}" -a "${fs}" != "none" ]; then
		msg_n "Creating ${name} fs..."
		zfs create -p \
			-o mountpoint=${mnt} ${fs} || err 1 " fail"
		echo " done"
	else
		mkdir -p ${mnt}
	fi
}

rollbackfs() {
	[ $# -ne 2 ] && eargs name mnt
................................................................................
}

umountfs() {
	[ $# -lt 1 ] && eargs mnt childonly
	local mnt=$1
	local childonly=$2
	local pattern

	[ -n "${childonly}" ] && pattern="/"

	[ -d "${mnt}" ] || return 0
	mnt=$(realpath ${mnt})
	mount | sort -r -k 2 | while read dev on pt opts; do
		case ${pt} in
		${mnt}${pattern}*)
			umount -f ${pt} || :

			[ "${dev#/dev/md*}" != "${dev}" ] && mdconfig -d -u ${dev#/dev/md*}

		;;
		esac
	done

	return 0
}

zfs_getfs() {
	[ $# -ne 1 ] && eargs mnt
	local mnt=$(realpath $1)
	mount -t zfs | awk -v n="${mnt}" ' $3 == n { print $1 }'
}
................................................................................
./etc/group
./etc/make.conf
./etc/make.conf.bak
./etc/passwd
./etc/master.passwd
./etc/shells
./var/mail/*
.${LOCALBASE:-/usr/local}/etc/gconf/gconf.xml.defaults
EOF
	fi
	mtree -X ${mnt}/poudriere/mtree.${name}exclude \
		-xcn -k uid,gid,mode,size \
		-p ${mnt} > ${mnt}/poudriere/mtree.${name}
}

................................................................................
	for p in ${devfspath} ; do
		devfs -m ${mnt}/dev/ rule apply path "${p}" unhide
	done
	if [ "${mnt##*/}" != "ref" ]; then
		[ ${JAILED} -eq 0 ] && mount -t fdescfs fdesc ${mnt}/dev/fd
		mount -t procfs proc ${mnt}/proc
		if [ -z "${NOLINUX}" ]; then
			[ "${arch}" = "i386" -o "${arch}" = "amd64" ] &&
				mount -t linprocfs linprocfs ${mnt}/compat/linux/proc
		fi
	fi


	return 0
}

use_options() {
	[ $# -ne 2 ] && eargs mnt optionsdir
	local mnt=$1
	local optionsdir=$2

................................................................................
	if [ "${optionsdir}" = "-" ]; then
		optionsdir="${POUDRIERED}/options"
	else
		optionsdir="${POUDRIERED}/${optionsdir}-options"
	fi
	[ -d "${optionsdir}" ] || return 1
	optionsdir=$(realpath ${optionsdir} 2>/dev/null)
	[ "${mnt##*/}" = "ref" ] &&
		msg "Mounting /var/db/ports from: ${optionsdir}"

	mount -t nullfs -o ro ${optionsdir} ${mnt}/var/db/ports ||
		err 1 "Failed to mount OPTIONS directory"

	return 0
}

mount_packages() {
	local mnt=$(my_path)
	mount -t nullfs "$@" ${POUDRIERE_DATA}/packages/${MASTERNAME} \
		${mnt}/packages ||
		err 1 "Failed to mount the packages directory "
}

do_portbuild_mounts() {
	[ $# -lt 3 ] && eargs mnt jname ptname setname
	local mnt=$1
	local jname=$2
................................................................................

	[ -d ${portsdir}/ports ] && portsdir=${portsdir}/ports

	[ "$(realpath ${DISTFILES_CACHE})" != \
		"$(realpath -q ${portsdir}/distfiles)" ] || err 1 \
		"DISTFILES_CACHE cannot be in the portsdir as the portsdir will be mounted read-only"





	mkdir -p ${POUDRIERE_DATA}/packages/${MASTERNAME}/All
	[ -d "${CCACHE_DIR:-/nonexistent}" ] &&
		mount -t nullfs ${CCACHE_DIR} ${mnt}/ccache

	[ -n "${MFSSIZE}" ] && mdmfs -M -S -o async -s ${MFSSIZE} md ${mnt}/wrkdirs
	[ ${TMPFS_WRKDIR} -eq 1 ] && mount -t tmpfs tmpfs ${mnt}/wrkdirs
	# Only show mounting messages once, not for every builder
	if [ ${mnt##*/} = "ref" ]; then
		[ -d "${CCACHE_DIR:-/nonexistent}" ] &&
			msg "Mounting ccache from: ${CCACHE_DIR}"

		msg "Mounting packages from: ${POUDRIERE_DATA}/packages/${MASTERNAME}"
	fi

	mount -t nullfs -o ro ${portsdir} ${mnt}/usr/ports ||
		err 1 "Failed to mount the ports directory "
	mount_packages -o ro
	mount -t nullfs ${DISTFILES_CACHE} ${mnt}/distfiles ||
		err 1 "Failed to mount the distfiles cache directory"

	optionsdir="${MASTERNAME}"
	[ -n "${setname}" ] && optionsdir="${optionsdir} ${jname}-${setname}"
	optionsdir="${optionsdir} ${jname}-${ptname} ${setname} ${ptname} ${jname} -"

	for opt in ${optionsdir}; do
		use_options ${mnt} ${opt} && break || continue
	done

	return 0
}

jail_start() {
	[ $# -lt 2 ] && eargs name ptname setname
	local name=$1
	local ptname=$2
	local setname=$3
................................................................................
		fi
	done
	jail_exists ${name} || err 1 "No such jail: ${name}"
	jail_runs ${MASTERNAME} && err 1 "jail already running: ${MASTERNAME}"
	export HOME=/root
	export USER=root
	export FORCE_PACKAGE=yes

	[ -z "${NO_PACKAGE_BUILDING}" ] && export PACKAGE_BUILDING=yes


	[ ${SET_STATUS_ON_START-1} -eq 1 ] && export STATUS=1
	msg_n "Creating the reference jail..."
	clonefs ${mnt} ${tomnt} clean
	echo " done"

	msg "Mounting system devices for ${MASTERNAME}"
................................................................................

	# If this is a builder, don't cleanup, the master will handle that.
	if [ -n "${MY_JOBID}" ]; then
		[ -n "${PKGNAME}" ] && clean_pool ${PKGNAME} 1 || :
		return 0
	fi

	[ -n "${MASTERNAME}" ] && rm -rf \
		${POUDRIERE_DATA}/packages/${MASTERNAME}/.new_packages

	# Only bother with this if using jails as this may be being ran
	# from queue.sh or daemon.sh, etc.
	if [ -n "${MASTERMNT}" -a -n "${MASTERNAME}" ]; then
		if [ -d ${MASTERMNT}/poudriere/var/run ]; then
			for pid in ${MASTERMNT}/poudriere/var/run/*.pid; do
				# Ensure there is a pidfile to read or break
				[ "${pid}" = "${MASTERMNT}/poudriere/var/run/*.pid" ] && break
................................................................................
	export CLEANED_UP=1
}

sanity_check_pkgs() {
	local ret=0
	local depfile
	[ ! -d ${POUDRIERE_DATA}/packages/${MASTERNAME}/All ] && return $ret
	dirempty ${POUDRIERE_DATA}/packages/${MASTERNAME}/All && return $ret
	for pkg in ${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.${PKG_EXT}; do
		# Check for non-empty directory with no packages in it
		[ "${pkg}" = "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.${PKG_EXT}" ] && break
		depfile=$(deps_file ${pkg})
		while read dep; do
			if [ ! -e "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/${dep}.${PKG_EXT}" ]; then
				ret=1
................................................................................
			break
		fi

		# Wait until it is done, but check on it every so often
		# This is done instead of a 'sleep' as it should recognize
		# the command has completed right away instead of waiting
		# on the 'sleep' to finish
		unset n; until trappedinfo=; read -t $read_timeout n <&7 ||
			[ -z "$trappedinfo" ]; do :; done
		if [ "${n}" = "done" ]; then
			wait $childpid || ret=1
			break
		fi
		# Not done, was a timeout, check the log time
	done

	exec 7<&-
	exec 7>&-

	return $ret
}

gather_distfiles() {
	[ $# -eq 2 ] || eargs portdir distfiles
	local portdir="$1"
	local distfiles="$2"
	local sub dists d special
	sub=$(injail make -C ${portdir} -VDIST_SUBDIR)
	dists=$(injail make -C ${portdir} -V_DISTFILES -V_PATCHFILES)
	specials=$(injail make -C ${portdir} -V_DEPEND_SPECIALS)
	job_msg_verbose "Providing distfiles for ${portdir}"
	for d in ${dists}; do
		[ -f ${DISTFILES_CACHE}/${sub}/${d} ] || continue
		echo ${DISTFILES_CACHE}/${sub}/${d}
	done | pax -rw -p p -s ",${DISTFILES_CACHE},,g" ${mnt}/portdistfiles

	for special in ${specials}; do
		gather_distfiles ${special} ${distfiles}
	done

	return 0
}

# Build+test port and return on first failure
build_port() {
	[ $# -ne 1 ] && eargs portdir
	local portdir=$1
	local port=${portdir##/usr/ports/}
	local targets="check-config pkg-depends fetch-depends fetch checksum \
				   extract-depends extract patch-depends patch build-depends \
				   lib-depends configure build install-mtree run-depends \
				   install package ${PORTTESTING:+deinstall}"
	local mnt=$(my_path)
	local log=$(log_path)
	local listfilecmd network

	local hangstatus

	for phase in ${targets}; do
		bset ${MY_JOBID} status "${phase}:${port}"
		job_msg_verbose "Status for build ${port}: ${phase}"
		if [ "${phase}" = "fetch" ]; then
			jstop
................................................................................
			echo "${listfilecmd} | xargs ldd 2>&1 | awk '/=>/ { print $3 }' | sort -u" > ${mnt}/shared.sh
			injail sh /shared.sh
			rm -f ${mnt}/shared.sh
			;;
		esac

		print_phase_header ${phase}

		if [ "${phase}" = "package" ]; then
			echo "PACKAGES=/new_packages" >> ${mnt}/etc/make.conf
			# Create sandboxed staging dir for new package for this build
			rm -rf "${POUDRIERE_DATA}/packages/${MASTERNAME}/.new_packages/${PKGNAME}"
			mkdir -p "${POUDRIERE_DATA}/packages/${MASTERNAME}/.new_packages/${PKGNAME}"
			mount -t nullfs \
				"${POUDRIERE_DATA}/packages/${MASTERNAME}/.new_packages/${PKGNAME}" \
				${mnt}/new_packages
		fi

		if [ "${phase#*-}" = "depends" ]; then
			# No need for nohang or PKGENV/PORT_FLAGS for *-depends
			injail make -C ${portdir} ${phase}
		else
			# 24 hours for 1 command, or 20 minutes with no log update
			nohang ${MAX_EXECUTION_TIME:-86400} ${NOHANG_TIME:-7200} \
				${log}/logs/${PKGNAME}.log \
				injail env ${PKGENV} ${PORT_FLAGS} \
				make -C ${portdir} ${phase}
			hangstatus=$? # This is done as it may return 1 or 2 or 3
			if [ $hangstatus -ne 0 ]; then
				# 1 = cmd failed, not a timeout
				# 2 = log timed out
				# 3 = cmd timeout
				if [ $hangstatus -eq 2 ]; then
					msg "Killing runaway build"
					bset ${MY_JOBID} status "${phase}/runaway:${port}"
					job_msg_verbose "Status for build ${port}: runaway"
				elif [ $hangstatus -eq 3 ]; then
					msg "Killing timed out build"
					bset ${MY_JOBID} status "${phase}/timeout:${port}"
					job_msg_verbose "Status for build ${port}: timeout"
				fi
				return 1
			fi
		fi

		if [ "${phase}" = "checksum" ]; then
			jstop
			jstart 0
		fi
		print_phase_footer

		if [ "${phase}" = "checksum" ]; then


			mkdir -p ${mnt}/portdistfiles
			echo "DISTDIR=/portdistfiles" >> ${mnt}/etc/make.conf



			gather_distfiles ${portdir} ${mnt}/portdistfiles
		fi

		if [ "${phase}" = "deinstall" ]; then
			msg "Checking for extra files and directories"
			PREFIX=$(injail env ${PORT_FLAGS} make -C ${portdir} -VPREFIX)
			bset ${MY_JOBID} status "leftovers:${port}"

			local add=$(mktemp ${mnt}/tmp/add.XXXXXX)
			local add1=$(mktemp ${mnt}/tmp/add1.XXXXXX)
			local del=$(mktemp ${mnt}/tmp/del.XXXXXX)
			local del1=$(mktemp ${mnt}/tmp/del1.XXXXXX)
			local mod=$(mktemp ${mnt}/tmp/mod.XXXXXX)
			local mod1=$(mktemp ${mnt}/tmp/mod1.XXXXXX)
			local die=0
................................................................................
				fi
				case $modtype in
				+)
					case "${ppath}" in
					*) echo "${ppath}" >> ${add} ;;
					esac
					;;
				-)
					# Skip if it is PREFIX and non-LOCALBASE. See misc/kdehier4
					# or mail/qmail for examples
					[ "${path#${mnt}}" = "${PREFIX}" -a \
						"${LOCALBASE}" != "${PREFIX}" ] && ignore_path=1

					if [ $ignore_path -eq 0 ]; then
						echo "${ppath}" >> ${del}
					fi
					;;
				M)
					[ -d "${path}" ] && continue
					case "${ppath}" in
					# This is a cache file for gio modules could be modified for any gio modules
					lib/gio/modules/giomodule.cache) ;;
					# removal of info files leaves entry uneasy to cleanup in info/dir
					# accept a modification of this file
					info/dir) ;;
					# The is pear database cache
					%%PEARDIR%%/.depdb|%%PEARDIR%%/.filemap) ;;
					#ls-R files from texmf are often regenerated
					*/ls-R);;
					# xmlcatmgr is constantly updating catalog.ports ignore modification to that file
					share/xml/catalog.ports);;
					*) echo "${ppath}" >> ${mod} ;;
					esac
					;;
				esac
			done
			sort ${add} > ${add1}
			sort ${del} > ${del1}
................................................................................
				die=1
				cat ${mod1}
			fi
			rm -f ${add} ${add1} ${del} ${del1} ${mod} ${mod1}
			[ $die -eq 0 ] || return 1
		fi
	done

	if [ -d "${POUDRIERE_DATA}/packages/${MASTERNAME}/.new_packages/${PKGNAME}" ]; then
		# everything was fine we can copy package the package to the package
		# directory
		find ${POUDRIERE_DATA}/packages/${MASTERNAME}/.new_packages/${PKGNAME} \
			-mindepth 1 \( -type f -or -type l \) | while read pkg_path; do
			pkg_file=${pkg_path#${POUDRIERE_DATA}/packages/${MASTERNAME}/.new_packages/${PKGNAME}}
			pkg_base=${pkg_file%/*}
			mkdir -p ${POUDRIERE_DATA}/packages/${MASTERNAME}/${pkg_base}
			mv ${pkg_path} ${POUDRIERE_DATA}/packages/${MASTERNAME}/${pkg_base}
		done
		rm -rf "${POUDRIERE_DATA}/packages/${MASTERNAME}/.new_packages/${PKGNAME}"
	fi

	bset ${MY_JOBID} status "idle:"
	return 0
}

# Save wrkdir and return path to file
save_wrkdir() {
................................................................................
	local phase="$4"
	local tardir=${POUDRIERE_DATA}/wrkdirs/${MASTERNAME}/${PTNAME}
	local tarname=${tardir}/${PKGNAME}.${WRKDIR_ARCHIVE_FORMAT}
	local mnted_portdir=${mnt}/wrkdirs/${portdir}

	[ -n "${SAVE_WRKDIR}" ] || return 0
	# Only save if not in fetch/checksum phase
	[ "${failed_phase}" != "fetch" -a "${failed_phase}" != "checksum" -a \
		"${failed_phase}" != "extract" ] || return 0

	mkdir -p ${tardir}

	# Tar up the WRKDIR, and ignore errors
	case ${WRKDIR_ARCHIVE_FORMAT} in
	tar) COMPRESSKEY="" ;;
	tgz) COMPRESSKEY="z" ;;
................................................................................
	err 1 "Unknown stuck queue bug detected. Give this information to poudriere developers:
$(find ${mnt}/poudriere/building ${mnt}/poudriere/pool ${mnt}/poudriere/deps)"
}

queue_empty() {
	local pool_dir
	local mnt=$(my_path)
	dirempty ${mnt}/poudriere/deps || return 1

	for pool_dir in ${POOL_BUCKET_DIRS}; do
		dirempty ${pool_dir} || return 1
	done

	return 0
}

mark_done() {
	[ $# -eq 1 ] || eargs pkgname
................................................................................
	msg "Hit CTRL+t at any time to see build progress and stats"

	while :; do
		builders_active=0
		for j in ${JOBS}; do
			name="${MASTERNAME}-job-${j}"
			if [ -f  "${mnt}/poudriere/var/run/${j}.pid" ]; then
				if pgrep -qF "${mnt}/poudriere/var/run/${j}.pid" 2>/dev/null; then
					builders_active=1
					continue
				fi
				read pkgname < ${mnt}/poudriere/var/run/${j}.pkgname
				rm -f ${mnt}/poudriere/var/run/${j}.pid \
					${mnt}/poudriere/var/run/${j}.pkgname
				bset ${j} status "idle:"
................................................................................
				# All work is done
				break
			fi
		fi

		[ ${builders_active} -eq 1 ] || deadlock_detected

		unset jobid; until trappedinfo=; read -t 30 jobid <&6 ||
			[ -z "$trappedinfo" ]; do :; done
	done
	exec 6<&-
	exec 6>&-
}

start_html_json() {
	json_main &
................................................................................
	local nbi=$(bget stats_ignored)
	local nbs=$(bget stats_skipped)
	local ndone=$((nbb + nbf + nbi + nbs))
	local nremaining=$((nbq - ndone))
	local real_parallel_jobs=${PARALLEL_JOBS}

	# If pool is empty, just return
	[ ${nremaining} -eq 0 ] && return 0

	# Minimize PARALLEL_JOBS to queue size
	[ ${PARALLEL_JOBS} -gt ${nremaining} ] && PARALLEL_JOBS=${nremaining##* }



	msg "Building ${nremaining} packages using ${PARALLEL_JOBS} builders"
	JOBS="$(jot -w %02d ${PARALLEL_JOBS})"

	start_html_json

	bset status "starting_jobs:"
................................................................................
	[ ${clean_rdepends} -eq 1 ] && port=$(cache_get_origin "${pkgname}")

	# Cleaning queue (pool is cleaned here)
	sh ${SCRIPTPREFIX}/clean.sh "${MASTERMNT}" "${pkgname}" ${clean_rdepends} | sort -u | while read skipped_pkgname; do
		skipped_origin=$(cache_get_origin "${skipped_pkgname}")
		badd ports.skipped "${skipped_origin} ${skipped_pkgname} ${pkgname}"
		job_msg "Skipping build of ${skipped_origin}: Dependent port ${port} failed"
		run_hook pkgbuild skipped "${skipped_origin}" "${skipped_pkgname}" "${port}"
	done

	balance_pool
}

print_phase_header() {
	printf "=======================<phase: %-13s>==========================\n" "$1"
................................................................................
	buildlog_start ${portdir}

	if [ -n "${ignore}" ]; then
		msg "Ignoring ${port}: ${ignore}"
		badd ports.ignored "${port} ${PKGNAME} ${ignore}"
		job_msg "Finished build of ${port}: Ignored: ${ignore}"
		clean_rdepends=1
		run_hook pkgbuild ignored "${port}" "${PKGNAME}" "${ignore}"







	else


		injail make -C ${portdir} clean
		if ! build_port ${portdir}; then
			build_failed=1
			failed_status=$(bget ${MY_JOBID} status)
			failed_phase=${failed_status%:*}

			save_wrkdir ${mnt} "${port}" "${portdir}" "${failed_phase}" || :
		elif [ -f ${mnt}/${portdir}/.keep ]; then
			save_wrkdir ${mnt} "${port}" "${portdir}" "noneed" ||:
		fi

		injail make -C ${portdir} clean


		if [ ${build_failed} -eq 0 ]; then
			badd ports.built "${port} ${PKGNAME}"
			job_msg "Finished build of ${port}: Success"
			run_hook pkgbuild success "${port}" "${PKGNAME}"
			# Cache information for next run
			pkg_cache_data "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/${PKGNAME}.${PKG_EXT}" ${port} || :
		else
			# Symlink the buildlog into errors/
			ln -s ../${PKGNAME}.log ${log}/logs/errors/${PKGNAME}.log
			badd ports.failed "${port} ${PKGNAME} ${failed_phase}"
			job_msg "Finished build of ${port}: Failed: ${failed_phase}"
			run_hook pkgbuild failed "${port}" "${PKGNAME}" "${failed_phase}" \
				"${log}/logs/errors/${PKGNAME}.log"
			clean_rdepends=1
		fi
	fi

	clean_pool ${PKGNAME} ${clean_rdepends}

	bset ${MY_JOBID} status "done:${port}"
................................................................................

	echo ${MY_JOBID} >&6
}

stop_build() {
	[ $# -eq 2 ] || eargs portdir logfile
	local portdir="$1"
	local mnt=$(my_path)
	local logfile="$2"

	umount -f ${mnt}/new_packages 2>/dev/null || :
	rm -rf "${POUDRIERE_DATA}/packages/${MASTERNAME}/.new_packages/${PKGNAME}"

	# 2 = HEADER+ps itself
	if [ $(injail ps aux | wc -l) -ne 2 ]; then
		msg "Leftover processes:"
		injail ps auxwwd | grep -v 'ps auxwwd'
	fi
	# Always kill to avoid missing anything
	injail kill -9 -1 2>/dev/null || :
................................................................................
	local pkg=$1
	local originfile=$(pkg_cache_dir ${pkg})/origin
	local origin=$2

	if [ ! -f "${originfile}" ]; then
		if [ -z "${origin}" ]; then
			if [ "${PKG_EXT}" = "tbz" ]; then
				origin=$(tar -xf "${pkg}" -O +CONTENTS | \
					awk -F: '$1 == "@comment ORIGIN" { print $2 }')
			else
				origin=$(pkg query -F "${pkg}" "%o")
			fi
		fi
		echo ${origin} > "${originfile}"
	else
		read origin < "${originfile}"
	fi
	echo ${origin}
}

pkg_get_dep_origin() {
	[ $# -ne 1 ] && eargs pkg
	local pkg=$1
	local dep_origin_file=$(pkg_cache_dir ${pkg})/dep_origin
	local compiled_dep_origins

	if [ ! -f "${dep_origin_file}" ]; then
		if [ "${PKG_EXT}" = "tbz" ]; then
			compiled_dep_origins=$(tar -xf "${pkg}" -O +CONTENTS | \
				awk -F: '$1 == "@comment DEPORIGIN" {print $2}' | tr '\n' ' ')
		else
			compiled_dep_origins=$(pkg query -F "${pkg}" '%do' | tr '\n' ' ')
		fi
		echo "${compiled_dep_origins}" > "${dep_origin_file}"
		echo "${compiled_dep_origins}"
		return 0
	fi

	cat "${dep_origin_file}"
}

pkg_get_options() {
	[ $# -ne 1 ] && eargs pkg
	local pkg=$1
	local optionsfile=$(pkg_cache_dir ${pkg})/options
	local compiled_options

	if [ ! -f "${optionsfile}" ]; then
		if [ "${PKG_EXT}" = "tbz" ]; then
			compiled_options=$(tar -xf "${pkg}" -O +CONTENTS | \
				awk -F: '$1 == "@comment OPTIONS" {print $2}' | tr ' ' '\n' | \
				sed -n 's/^\+\(.*\)/\1/p' | sort | tr '\n' ' ')
		else
			compiled_options=$(pkg query -F "${pkg}" '%Ov %Ok' | \
				awk '$1 == "on" {print $2}' | sort | tr '\n' ' ')
		fi
		echo "${compiled_options}" > "${optionsfile}"
		echo "${compiled_options}"
		return 0
	fi
	# optionsfile is multi-line, no point for read< trick here
	cat "${optionsfile}"
................................................................................
	local origin=$2
	local cachedir=$(pkg_cache_dir ${pkg})
	local originfile=${cachedir}/origin

	mkdir -p $(pkg_cache_dir ${pkg})
	pkg_get_options ${pkg} > /dev/null
	pkg_get_origin ${pkg} ${origin} > /dev/null
	pkg_get_dep_origin ${pkg} > /dev/null
	deps_file ${pkg} > /dev/null
	set -e
}

pkg_to_pkgname() {
	[ $# -ne 1 ] && eargs pkg
	local pkg=$1
................................................................................
}

# Deleted cached information for stale packages (manually removed)
delete_stale_pkg_cache() {
	local pkgname
	local cachedir=$(cache_dir)
	[ ! -d ${cachedir} ] && return 0
	dirempty ${cachedir} && return 0
	for pkg in ${cachedir}/*.${PKG_EXT}; do
		pkg_file=${pkg##*/}
		# If this package no longer exists in the PKGDIR, delete the cache.
		[ ! -e "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/${pkg_file}" ] &&
			clear_pkg_cache ${pkg}

	done

	return 0
}

delete_old_pkg() {
	local pkg="$1"
	local mnt=$(my_path)
	local o v v2 compiled_options current_options current_deps compiled_deps
	if [ "${pkg##*/}" = "repo.txz" ]; then
		msg "Removing invalid pkg repo file: ${pkg}"
		rm -f ${pkg}
		return 0
	fi

	mkdir -p $(pkg_cache_dir ${pkg})
................................................................................
	v2=$(cache_get_pkgname ${o})
	v2=${v2##*-}
	if [ "$v" != "$v2" ]; then
		msg "Deleting old version: ${pkg##*/}"
		delete_pkg ${pkg}
		return 0
	fi

	current_deps=$(injail make -C /usr/ports/${o} run-depends-list | sed 's,/usr/ports/,,g' | tr '\n' ' ')
	compiled_deps=$(pkg_get_dep_origin ${pkg})
	for d in ${current_deps}; do
		case " $compiled_deps " in
		*\ $d\ *) ;;
		*)
			msg "Direct dependency change, deleting: ${pkg##*/}"
			delete_pkg ${pkg}
			return 0
			;;
		esac
	done

	# Check if the compiled options match the current options from make.conf and /var/db/options
	if [ "${CHECK_CHANGED_OPTIONS:-no}" != "no" ]; then
		current_options=$(injail make -C /usr/ports/${o} pretty-print-config | \
			tr ' ' '\n' | sed -n 's/^\+\(.*\)/\1/p' | sort | tr '\n' ' ')
		compiled_options=$(pkg_get_options ${pkg})

		if [ "${compiled_options}" != "${current_options}" ]; then
			msg "Options changed, deleting: ${pkg##*/}"
			if [ "${CHECK_CHANGED_OPTIONS}" = "verbose" ]; then
				msg "Pkg: ${compiled_options}"
				msg "New: ${current_options}"
................................................................................
			return 0
		fi
	fi
}

delete_old_pkgs() {
	[ ! -d ${POUDRIERE_DATA}/packages/${MASTERNAME}/All ] && return 0
	dirempty ${POUDRIERE_DATA}/packages/${MASTERNAME}/All && return 0
	parallel_start
	for pkg in ${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.${PKG_EXT}; do
		# Check for non-empty directory with no packages in it
		[ "${pkg}" = "${POUDRIERE_DATA}/packages/${MASTERNAME}/All/*.${PKG_EXT}" ] && break
		parallel_run delete_old_pkg "${pkg}"
	done
	parallel_stop
................................................................................
}

lock_acquire() {
	[ $# -ne 1 ] && eargs lockname
	local lockname=$1

	while :; do
		mkdir ${POUDRIERE_DATA}/.lock-${MASTERNAME}-${lockname} 2>/dev/null &&
			break

		sleep 0.1
	done
}

lock_release() {
	[ $# -ne 1 ] && eargs lockname
	local lockname=$1
................................................................................
	local cache_origin_pkgname=${MASTERMNT}/poudriere/var/cache/origin-pkgname/${origin%%/*}_${origin##*/}
	local cache_pkgname_origin

	[ -f ${cache_origin_pkgname} ] && read pkgname < ${cache_origin_pkgname}

	# Add to cache if not found.
	if [ -z "${pkgname}" ]; then
		[ -d "${MASTERMNT}/usr/ports/${origin}" ] ||
			err 1 "Invalid port origin '${origin}' not found."
		pkgname=$(injail make -C /usr/ports/${origin} -VPKGNAME ||
			err 1 "Error getting PKGNAME for ${origin}")
		# Make sure this origin did not already exist
		existing_origin=$(cache_get_origin "${pkgname}" 2>/dev/null || :)
		# It may already exist due to race conditions, it is not harmful. Just ignore.
		if [ "${existing_origin}" != "${origin}" ]; then
			[ -n "${existing_origin}" ] &&
				err 1 "Duplicated origin for ${pkgname}: ${origin} AND ${existing_origin}. Rerun with -vv to see which ports are depending on these."
			echo "${pkgname}" > ${cache_origin_pkgname}
			cache_pkgname_origin="${MASTERMNT}/poudriere/var/cache/pkgname-origin/${pkgname}"
			echo "${origin}" > "${cache_pkgname_origin}"
		fi
	fi

................................................................................
	local pkg_pooldir="${mnt}/poudriere/deps/${pkgname}"
	mkdir "${pkg_pooldir}" 2>/dev/null || return 0

	msg_verbose "Computing deps for ${port}"

	for dep_port in `list_deps ${port}`; do
		msg_debug "${port} depends on ${dep_port}"
		[ "${port}" != "${dep_port}" ] ||
			err 1 "${port} incorrectly depends on itself. Please contact maintainer of the port to fix this."
		# Detect bad cat/origin/ dependency which pkgng will not register properly
		[ "${dep_port}" = "${dep_port%/}" ] ||
			err 1 "${port} depends on bad origin '${dep_port}'; Please contact maintainer of the port to fix this."
		dep_pkgname=$(cache_get_pkgname ${dep_port})

		# Only do this if it's not already done, and not ALL, as everything will
		# be touched anyway
		[ ${ALL:-0} -eq 0 ] && ! [ -d "${mnt}/poudriere/deps/${dep_pkgname}" ] &&
			compute_deps "${dep_port}" "${dep_pkgname}"

		touch "${pkg_pooldir}/${dep_pkgname}"
		mkdir -p "${mnt}/poudriere/rdeps/${dep_pkgname}"
		ln -sf "${pkg_pooldir}/${dep_pkgname}" \
			"${mnt}/poudriere/rdeps/${dep_pkgname}/${pkgname}"
	done
................................................................................
}

listed_ports() {
	if [ ${ALL:-0} -eq 1 ]; then
		PORTSDIR=$(pget ${PTNAME} mnt)
		[ -d "${PORTSDIR}/ports" ] && PORTSDIR="${PORTSDIR}/ports"
		for cat in $(awk '$1 == "SUBDIR" { print $3}' ${PORTSDIR}/Makefile); do
			awk -v cat=${cat} '$1 == "SUBDIR" { print cat"/"$3}' ${PORTSDIR}/${cat}/Makefile
		done
		return 0
	fi
	if [ -z "${LISTPORTS}" ]; then
		[ -n "${LISTPKGS}" ] &&
			grep -v -E '(^[[:space:]]*#|^[[:space:]]*$)' ${LISTPKGS}

	else
		echo ${LISTPORTS} | tr ' ' '\n'
	fi
}

parallel_exec() {
	local cmd="$1"
................................................................................
	local log=$(log_path)
	local n port pn nbq resuming_build

	msg "Calculating ports order and dependencies"
	mkdir -p "${MASTERMNT}/poudriere"
	[ ${TMPFS_DATA} -eq 1 ] && mount -t tmpfs tmpfs "${MASTERMNT}/poudriere"
	rm -rf "${MASTERMNT}/poudriere/var/cache/origin-pkgname" \
		"${MASTERMNT}/poudriere/var/cache/pkgname-origin" 2>/dev/null || :
	mkdir -p "${MASTERMNT}/poudriere/building" \
		"${MASTERMNT}/poudriere/pool" \
		"${MASTERMNT}/poudriere/deps" \
		"${MASTERMNT}/poudriere/rdeps" \
		"${MASTERMNT}/poudriere/var/run" \
		"${MASTERMNT}/poudriere/var/cache" \
		"${MASTERMNT}/poudriere/var/cache/origin-pkgname" \
................................................................................
	mkdir -p ${log}/logs ${log}/logs/errors
	ln -sfh ${BUILDNAME} ${log%/*}/latest
	cp ${HTMLPREFIX}/* ${log}

	bset status "computingdeps:"
	parallel_start
	for port in $(listed_ports); do
		[ -d "${MASTERMNT}/usr/ports/${port}" ] ||
			err 1 "Invalid port origin: ${port}"
		parallel_run compute_deps ${port}
	done
	parallel_stop

	bset status "sanity:"

	if [ ${CLEAN_LISTED:-0} -eq 1 ]; then
................................................................................
		msg "Sanity checking the repository"
		delete_stale_pkg_cache
		delete_old_pkgs

		while :; do
			sanity_check_pkgs && break
		done


		msg "Deleting stale symlinks"
		find -L ${POUDRIERE_DATA}/packages/${MASTERNAME} -type l \
			-exec rm -f {} +

		msg "Deleting empty directories"
		find ${POUDRIERE_DATA}/packages/${MASTERNAME} -type d -mindepth 1 \
			-empty -delete
	fi

	bset status "cleaning:"
	msg "Cleaning the build queue"
	export LOCALBASE=${LOCALBASE:-/usr/local}
	for pn in $(ls ${MASTERMNT}/poudriere/deps/); do
		if [ -f "${MASTERMNT}/packages/All/${pn}.${PKG_EXT}" ]; then
			find_all_pool_references "${pn}"
		fi
................................................................................

balance_pool() {
	# Don't bother if disabled
	[ ${POOL_BUCKETS} -gt 0 ] || return 0

	local pkgname pkg_dir dep_count rdep lock

	! dirempty ${MASTERMNT}/poudriere/pool/unbalanced || return 0
	# Avoid running this in parallel, no need
	lock=${MASTERMNT}/poudriere/.lock-balance_pool
	mkdir ${lock} 2>/dev/null || return 0

	if [ -n "${MY_JOBID}" ]; then
		bset ${MY_JOBID} status "balancing_pool:"
	else
................................................................................
	echo "#### ${makeconf} ####" >> ${mnt}/etc/make.conf
	cat "${makeconf}" >> ${mnt}/etc/make.conf
}

RESOLV_CONF=""
STATUS=0 # out of jail #

[ -f ${SCRIPTPREFIX}/../../etc/poudriere.conf ] ||
	err 1 "Unable to find ${SCRIPTPREFIX}/../../etc/poudriere.conf"

. ${SCRIPTPREFIX}/../../etc/poudriere.conf
POUDRIERED=${SCRIPTPREFIX}/../../etc/poudriere.d
LIBEXECPREFIX=${SCRIPTPREFIX}/../../libexec/poudriere
AWKPREFIX=${SCRIPTPREFIX}/awk
HTMLPREFIX=${SCRIPTPREFIX}/html
HOOKDIR=${POUDRIERED}/hooks
PATH="${LIBEXECPREFIX}:${PATH}"

# If the zfs module is not loaded it means we can't have zfs
[ -z "${NO_ZFS}" ] && lsvfs zfs >/dev/null 2>&1 || NO_ZFS=yes
# Short circuit to prevent running zpool(1) and loading zfs.ko
[ -z "${NO_ZFS}" ] && [ -z "$(zpool list -H -o name 2>/dev/null)" ] && NO_ZFS=yes

[ -z "${NO_ZFS}" -a -z ${ZPOOL} ] && err 1 "ZPOOL variable is not set"
[ -z ${BASEFS} ] && err 1 "Please provide a BASEFS variable in your poudriere.conf"

trap sig_handler SIGINT SIGTERM SIGKILL
trap exit_handler EXIT
trap siginfo_handler SIGINFO
................................................................................
			# Delete the old properties
			zfs inherit -r ${NS}:type ${fs}
			zfs inherit -r ${NS}:name ${fs}
			zfs inherit -r ${NS}:method ${fs}
		done
	if [ -f ${POUDRIERED}/portstrees ]; then
		while read name method mnt; do
			[ -z "${name###*}" ] && continue # Skip comments
			msg "Converting the ${name} ports tree"
			mkdir ${POUDRIERED}/ports/${name}
			echo ${method} > ${POUDRIERED}/ports/${name}/method
			echo ${mnt} > ${POUDRIERED}/ports/${name}/mnt
		done < ${POUDRIERED}/portstrees
		rm -f ${POUDRIERED}/portstrees
	fi

Changes to src/share/poudriere/daemon.sh.

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    -k        -- kill the running daemon"

    exit 1
}

SCRIPTPATH=`realpath $0`
SCRIPTPREFIX=`dirname ${SCRIPTPATH}`
LIBEXECPREFIX=`realpath ${SCRIPTPREFIX}/../../libexec/poudriere`
PTNAME="default"
NODAEMONIZE=0
KILL=0

. ${SCRIPTPREFIX}/common.sh

if [ -z "${DAEMON_ARGS_PARSED}" ]; then
................................................................................
		echo "$$" > ${PIDFILE}
	fi
fi

while :; do
	next=$(find ${WATCHDIR} -type f -depth 1 -print -quit 2>/dev/null)
	if [ -z "${next}" ]; then
		${LIBEXECPREFIX}/dirwatch ${WATCHDIR}
		continue
	fi
	POUDRIERE_ARGS=$(sed -n "s/^POUDRIERE_ARGS: //p" ${next})
	mkdir -p ${POUDRIERE_DATA}/logs/daemon
	poudriere ${POUDRIERE_ARGS} > ${POUDRIERE_DATA}/logs/daemon/${next##*/}.log
	rm -f ${next}
done







<







 







|







34
35
36
37
38
39
40

41
42
43
44
45
46
47
..
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
    -k        -- kill the running daemon"

    exit 1
}

SCRIPTPATH=`realpath $0`
SCRIPTPREFIX=`dirname ${SCRIPTPATH}`

PTNAME="default"
NODAEMONIZE=0
KILL=0

. ${SCRIPTPREFIX}/common.sh

if [ -z "${DAEMON_ARGS_PARSED}" ]; then
................................................................................
		echo "$$" > ${PIDFILE}
	fi
fi

while :; do
	next=$(find ${WATCHDIR} -type f -depth 1 -print -quit 2>/dev/null)
	if [ -z "${next}" ]; then
		dirwatch ${WATCHDIR}
		continue
	fi
	POUDRIERE_ARGS=$(sed -n "s/^POUDRIERE_ARGS: //p" ${next})
	mkdir -p ${POUDRIERE_DATA}/logs/daemon
	poudriere ${POUDRIERE_ARGS} > ${POUDRIERE_DATA}/logs/daemon/${next##*/}.log
	rm -f ${next}
done

Changes to src/share/poudriere/distclean.sh.

73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
done

shift $((OPTIND-1))

export PORTSDIR=$(pget ${PTNAME} mnt)
[ -d "${PORTSDIR}/ports" ] && PORTSDIR="${PORTSDIR}/ports"
[ -z "${PORTSDIR}" ] && err 1 "No such ports tree: ${PTNAME}"

[ -d ${DISTFILES_CACHE:-/nonexistent} ] || err 1 "DISTFILES_CACHE directory does not exists. (c.f. poudriere.conf)"

DISTFILES_LIST=$(mktemp -t poudriere_distfiles)
CLEANUP_HOOK=distfiles_cleanup
distfiles_cleanup() {
	rm -f ${DISTFILES_LIST} ${DISTFILES_LIST}.expected \
		${DISTFILES_LIST}.actual ${DISTFILES_LIST}.unexpected \
		2>/dev/null







>
|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
done

shift $((OPTIND-1))

export PORTSDIR=$(pget ${PTNAME} mnt)
[ -d "${PORTSDIR}/ports" ] && PORTSDIR="${PORTSDIR}/ports"
[ -z "${PORTSDIR}" ] && err 1 "No such ports tree: ${PTNAME}"
[ -d ${DISTFILES_CACHE:-/nonexistent} ] ||
	err 1 "DISTFILES_CACHE directory does not exists. (c.f. poudriere.conf)"

DISTFILES_LIST=$(mktemp -t poudriere_distfiles)
CLEANUP_HOOK=distfiles_cleanup
distfiles_cleanup() {
	rm -f ${DISTFILES_LIST} ${DISTFILES_LIST}.expected \
		${DISTFILES_LIST}.actual ${DISTFILES_LIST}.unexpected \
		2>/dev/null

Changes to src/share/poudriere/jail.sh.

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
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
193
194
195
196
197
198
199
200
201





202
203
204
205
206
207
208
209
210
211
...
226
227
228
229
230
231
232





233
234
235
236
237
238
239
...
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
...
270
271
272
273
274
275
276
277
278

279
280
281
282
283
284
285
286
287
288
289
290
...
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
...
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
...
498
499
500
501
502
503
504




505
506
507
508
509
510
511
...
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
...
556
557
558
559
560
561
562



563
    -m method     -- When used with -c, overrides the method to use by default.
                     Could also be \"http\", \"svn\", \"svn+http\",
                     \"svn+https\", \"svn+file\", \"svn+ssh\", \"csup\".
                     Please note that with svn and csup the world will be
                     built. Note that building from sources can use src.conf
		     and jail-src.conf from /usr/local/etc/poudriere.d/.
		     Other possible method are: \"allbsd\" retrieve a
		     snapshot from allbsd.org's website or \"gjb\" for a
		     snapshot from Glen Barber's website.
    -p tree       -- Specify which ports tree the jail to start/stop with

    -t version    -- version to upgrade to
    -z set        -- Specify which SET the jail to start/stop with
"
	exit 1
}

list_jail() {
	[ ${QUIET} -eq 0 ] && \
		printf '%-20s %-20s %-7s %-7s\n' "JAILNAME" "VERSION" "ARCH" "METHOD"
	for j in $(find ${POUDRIERED}/jails -type d -maxdepth 1 -mindepth 1 -print); do
		name=${j##*/}
		version=$(jget ${name} version)
		arch=$(jget ${name} arch)
		method=$(jget ${name} method)
		printf '%-20s %-20s %-7s %-7s\n' "${name}" "${version}" "${arch}" "${method}"
................................................................................
	done
}

delete_jail() {
	test -z ${JAILNAME} && usage
	jail_exists ${JAILNAME} || err 1 "No such jail: ${JAILNAME}"
	msg_n "Removing ${JAILNAME} jail..."
	destroyfs jail ${JAILNAME}
	rm -rf ${POUDRIERED}/jails/${JAILNAME} || :
	echo done
}

cleanup_new_jail() {
	msg "Error while creating jail, cleaning up." >&2
	delete_jail
}

................................................................................
update_version() {
	local release="$1"
	local login_env osversion

	osversion=`awk '/\#define __FreeBSD_version/ { print $3 }' ${JAILMNT}/usr/include/sys/param.h`
	login_env=",UNAME_r=${release},UNAME_v=FreeBSD ${release},OSVERSION=${osversion}"

	if [ "${ARCH}" = "i386" -a "${REALARCH}" = "amd64" ];then
		login_env="${login_env},UNAME_p=i386,UNAME_m=i386"
	fi

	sed -i "" -e "s/:\(setenv.*\):/:\1${login_env}:/" ${JAILMNT}/etc/login.conf
	cap_mkdb ${JAILMNT}/etc/login.conf
}

update_jail() {
	local netargs
	jail_exists ${JAILNAME} || err 1 "No such jail: ${JAILNAME}"
	jail_runs && \
		err 1 "Unable to remove jail ${JAILNAME}: it is running"

	METHOD=$(jget ${JAILNAME} method)
	if [ -z "${METHOD}" -o "${METHOD}" = "-" ]; then
		METHOD="ftp"
		jset ${JAILNAME} method ${METHOD}
	fi
	msg "Upgrading using ${METHOD}"
	case ${METHOD} in
	ftp)
		MASTERMNT=$(jget ${JAILNAME} mnt)
		MASTERNAME=${JAILNAME}
		jstart 1
		if [ -z "${TORELEASE}" ]; then
			injail /usr/sbin/freebsd-update fetch install
		else
			yes | injail env PAGER=/bin/cat /usr/sbin/freebsd-update -r ${TORELEASE} upgrade install || err 1 "Fail to upgrade system"

			yes | injail env PAGER=/bin/cat /usr/sbin/freebsd-update install || err 1 "Fail to upgrade system"

			jset ${JAILNAME} version ${TORELEASE}
		fi
		jstop
		markfs clean ${JAILMNT}
		;;
	csup)
		install_from_csup
................................................................................
		unset CCACHE_TEMPDIR
	fi

	msg "Starting make buildworld with ${PARALLEL_JOBS} jobs"
	make -C ${JAILMNT}/usr/src buildworld ${MAKE_JOBS} ${MAKEWORLDARGS} || err 1 "Fail to build world"
	msg "Starting make installworld"
	make -C ${JAILMNT}/usr/src installworld DESTDIR=${JAILMNT} || err 1 "Fail to install world"
	make -C ${JAILMNT}/usr/src DESTDIR=${JAILMNT} distrib-dirs && \
	make -C ${JAILMNT}/usr/src DESTDIR=${JAILMNT} distribution
}

install_from_svn() {
	local UPDATE=0
	local proto
	[ -d ${JAILMNT}/usr/src ] && UPDATE=1
................................................................................
	svn+https) proto="https" ;;
	svn+ssh) proto="svn+ssh" ;;
	svn+file) proto="file" ;;
	svn) proto="svn" ;;
	esac
	if [ ${UPDATE} -eq 0 ]; then
		msg_n "Checking out the sources from svn..."
		svn -q co ${proto}://${SVN_HOST}/base/${VERSION} ${JAILMNT}/usr/src || err 1 "Fail "
		echo " done"





	else
		msg_n "Updating the sources from svn..."
		svn -q update ${JAILMNT}/usr/src || err 1 "Fail "
		echo " done"
	fi
	build_and_install_world
}

install_from_csup() {
	local UPDATE=0
................................................................................
}

install_from_ftp() {
	mkdir ${JAILMNT}/fromftp
	local URL V

	V=${ALLBSDVER:-${VERSION}}





	if [ ${V%%.*} -lt 9 ]; then
		msg "Fetching sets for FreeBSD ${V} ${ARCH}"
		case ${METHOD} in
		ftp|gjb)
			case ${VERSION} in
				*-PRERELEASE|*-STABLE) type=snapshots ;;
				*) type=releases ;;
................................................................................
			echo ${FREEBSD_HOST} | egrep -E "(_PROTO_|_CHANGE_THIS_)" > /dev/null
			if [ $? -eq 0 ]; then
				msg "FREEBSD_HOST from config invalid; defaulting to http://ftp.freebsd.org"
				FREEBSD_HOST="http://ftp.freebsd.org"
			fi
			URL="${FREEBSD_HOST}/pub/FreeBSD/${type}/${ARCH}/${V}" ;;
		allbsd) URL="https://pub.allbsd.org/FreeBSD-snapshots/${ARCH}-${ARCH}/${V}-JPSNAP/ftp" ;;

		esac
		DISTS="base dict src games"
		[ ${ARCH} = "amd64" ] && DISTS="${DISTS} lib32"
		for dist in ${DISTS}; do
			fetch_file ${JAILMNT}/fromftp/ ${URL}/$dist/CHECKSUM.SHA256 || \
				err 1 "Fail to fetch checksum file"
			sed -n "s/.*(\(.*\...\)).*/\1/p" \
				${JAILMNT}/fromftp/CHECKSUM.SHA256 | \
				while read pkg; do
				[ ${pkg} = "install.sh" ] && continue
				# Let's retry at least one time
				fetch_file ${JAILMNT}/fromftp/ ${URL}/${dist}/${pkg}
			done
		done

................................................................................
				s*)
					APPEND="usr/src"
					;;
				*)
					APPEND=""
					;;
			esac
			cat ${JAILMNT}/fromftp/${SET}.* | \
				tar --unlink -xpf - -C ${JAILMNT}/${APPEND} || err 1 " Fail" && echo " done"

		done
	else
		local type
		case ${METHOD} in
			ftp|gjb)
				case ${VERSION} in
					*-CURRENT|*-PRERELEASE|*-STABLE) type=snapshots ;;
					*) type=releases ;;
				esac

				# Check that the defaults have been changed
				echo ${FREEBSD_HOST} | egrep -E "(_PROTO_|_CHANGE_THIS_)" > /dev/null
................................................................................
		esac
		DISTS="base.txz src.txz games.txz"
		[ ${ARCH} = "amd64" ] && DISTS="${DISTS} lib32.txz"
		for dist in ${DISTS}; do
			msg "Fetching ${dist} for FreeBSD ${V} ${ARCH}"
			fetch_file ${JAILMNT}/fromftp/${dist} ${URL}/${dist}
			msg_n "Extracting ${dist}..."
			tar -xpf ${JAILMNT}/fromftp/${dist} -C  ${JAILMNT}/ || err 1 " fail" && echo " done"

		done
	fi

	msg_n "Cleaning up..."
	rm -rf ${JAILMNT}/fromftp/
	echo " done"
}

create_jail() {
	jail_exists ${JAILNAME} && err 2 "The jail ${JAILNAME} already exists"

	test -z ${VERSION} && usage


	[ "${JAILNAME#*.*}" = "${JAILNAME}" ] || err 1 "The jailname can not contain a period (.). See jail(8)"

	if [ -z ${JAILMNT} ]; then
		[ -z ${BASEFS} ] && err 1 "Please provide a BASEFS variable in your poudriere.conf"
		JAILMNT=${BASEFS}/jails/${JAILNAME}
	fi

	if [ -z ${JAILFS} ] ; then
		[ -z ${ZPOOL} ] && err 1 "Please provide a ZPOOL variable in your poudriere.conf"
		JAILFS=${ZPOOL}${ZROOTFS}/jails/${JAILNAME}
	fi

	case ${METHOD} in
	ftp)
		FCT=install_from_ftp
		;;
	gjb)
		FCT=install_from_ftp
		GJBVERSION=${VERSION}
		VERSION=${VERSION%%-*}
		;;
	allbsd)
		FCT=install_from_ftp
		ALLBSDVER=`fetch -qo - \
			https://pub.allbsd.org/FreeBSD-snapshots/${ARCH}-${ARCH}/ | \
			sed -n "s,.*href=\"\(.*${VERSION}.*\)-JPSNAP/\".*,\1,p" | \
			sort -k 3 -t - -r | head -n 1 `
		if [ -z ${ALLBSDVER} ]; then
			err 1 "Unknown version $VERSION"
		fi

		OIFS=${IFS}
		IFS=-
		set -- ${ALLBSDVER}
		IFS=${OIFS}
		RELEASE="${ALLBSDVER}-JPSNAP/ftp"
		;;
................................................................................
	svn*)
		SVN=`which svn`
		test -z ${SVN} && err 1 "You need svn on your host to use svn method"
		case ${VERSION} in
			stable/*![0-9]*)
				err 1 "bad version number for stable version"
				;;



			release/*![0-9]*.[0-9].[0-9])
				err 1 "bad version number for release version"
				;;
			releng/*![0-9]*.[0-9])
				err 1 "bad version number for releng version"
				;;
			stable/*|head|release/*|releng/*.[0-9]) ;;
			*)
				err 1 "version with svn should be: head or stable/N or release/N or releng/N"
				;;
		esac
		FCT=install_from_svn
		;;
	csup)
		case ${VERSION} in
			.)
................................................................................
	${FCT}

	eval `grep "^[RB][A-Z]*=" ${JAILMNT}/usr/src/sys/conf/newvers.sh `
	RELEASE=${REVISION}-${BRANCH}
	jset ${JAILNAME} version ${RELEASE}
	update_version ${RELEASE}

	if [ "${ARCH}" = "i386" -a "${REALARCH}" = "amd64" ];then
		cat > ${JAILMNT}/etc/make.conf << EOF
ARCH=i386
MACHINE=i386
MACHINE_ARCH=i386
EOF

	fi
................................................................................
PTNAME=default
SETNAME=""

SCRIPTPATH=`realpath $0`
SCRIPTPREFIX=`dirname ${SCRIPTPATH}`
. ${SCRIPTPREFIX}/common.sh

while getopts "J:j:v:a:z:m:n:f:M:sdklqcip:ut:z:" FLAG; do
	case "${FLAG}" in
		j)
			JAILNAME=${OPTARG}
			;;
		J)
			PARALLEL_JOBS=${OPTARG}
			;;
		v)
			VERSION=${OPTARG}
			;;
		a)
			if [ "${REALARCH}" != "amd64" -a "${REALARCH}" != ${OPTARG} ]; then
				err 1 "Only amd64 host can choose another architecture"
			fi
			ARCH=${OPTARG}
			;;
		m)
			METHOD=${OPTARG}
			;;
		f)
			JAILFS=${OPTARG}
................................................................................
			;;
		d)
			DELETE=1
			;;
		p)
			PTNAME=${OPTARG}
			;;




		q)
			QUIET=1
			;;
		u)
			UPDATE=1
			;;
		t)
................................................................................
		*)
			usage
			;;
	esac
done

METHOD=${METHOD:-ftp}
if [ -n "${JAILNAME}" ] && [ ${CREATE} -eq 0 ]; then
	ARCH=$(jget ${JAILNAME} arch)
	JAILFS=$(jget ${JAILNAME} fs)
	JAILMNT=$(jget ${JAILNAME} mnt)
fi


[ $(( CREATE + LIST + STOP + START + DELETE + UPDATE )) -lt 1 ] && usage

case "${CREATE}${LIST}${STOP}${START}${DELETE}${UPDATE}" in
	100000)
		test -z ${JAILNAME} && usage
		create_jail
		;;
	010000)
		list_jail
................................................................................
		test -z ${JAILNAME} && usage
		delete_jail
		;;
	000001)
		test -z ${JAILNAME} && usage
		update_jail
		;;



esac







|
|

>







|







 







|

|







 







|

<








|









|






|
>
|
>







 







|







 







|

>
>
>
>
>


|







 







>
>
>
>
>







 







>




|


|







 







|
|
>




|







 







|
>













>
|






|





|


<
<
<
<
<






<
|
<







 







>
>
>






|

|







 







|







 







|











|

<







 







>
>
>
>







 







|





<
<
<







 







>
>
>

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
...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
...
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
...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
...
533
534
535
536
537
538
539
540
541
542
543
544
545



546
547
548
549
550
551
552
...
568
569
570
571
572
573
574
575
576
577
578
    -m method     -- When used with -c, overrides the method to use by default.
                     Could also be \"http\", \"svn\", \"svn+http\",
                     \"svn+https\", \"svn+file\", \"svn+ssh\", \"csup\".
                     Please note that with svn and csup the world will be
                     built. Note that building from sources can use src.conf
		     and jail-src.conf from /usr/local/etc/poudriere.d/.
		     Other possible method are: \"allbsd\" retrieve a
		     snapshot from allbsd.org's website or \"ftp-archive\"
		     for old releases that're no longer available on \"ftp\".
    -p tree       -- Specify which ports tree the jail to start/stop with
    -P patch      -- Specify a patch file to apply to the source before committing.
    -t version    -- version to upgrade to
    -z set        -- Specify which SET the jail to start/stop with
"
	exit 1
}

list_jail() {
	[ ${QUIET} -eq 0 ] &&
		printf '%-20s %-20s %-7s %-7s\n' "JAILNAME" "VERSION" "ARCH" "METHOD"
	for j in $(find ${POUDRIERED}/jails -type d -maxdepth 1 -mindepth 1 -print); do
		name=${j##*/}
		version=$(jget ${name} version)
		arch=$(jget ${name} arch)
		method=$(jget ${name} method)
		printf '%-20s %-20s %-7s %-7s\n' "${name}" "${version}" "${arch}" "${method}"
................................................................................
	done
}

delete_jail() {
	test -z ${JAILNAME} && usage
	jail_exists ${JAILNAME} || err 1 "No such jail: ${JAILNAME}"
	msg_n "Removing ${JAILNAME} jail..."
	destroyfs ${JAILMNT} jail
	rm -rf ${POUDRIERED}/jails/${JAILNAME} || :
	echo " done"
}

cleanup_new_jail() {
	msg "Error while creating jail, cleaning up." >&2
	delete_jail
}

................................................................................
update_version() {
	local release="$1"
	local login_env osversion

	osversion=`awk '/\#define __FreeBSD_version/ { print $3 }' ${JAILMNT}/usr/include/sys/param.h`
	login_env=",UNAME_r=${release},UNAME_v=FreeBSD ${release},OSVERSION=${osversion}"

	[ "${ARCH}" = "i386" -a "${REALARCH}" = "amd64" ] &&
		login_env="${login_env},UNAME_p=i386,UNAME_m=i386"


	sed -i "" -e "s/:\(setenv.*\):/:\1${login_env}:/" ${JAILMNT}/etc/login.conf
	cap_mkdb ${JAILMNT}/etc/login.conf
}

update_jail() {
	local netargs
	jail_exists ${JAILNAME} || err 1 "No such jail: ${JAILNAME}"
	jail_runs ${JAILNAME} &&
		err 1 "Unable to remove jail ${JAILNAME}: it is running"

	METHOD=$(jget ${JAILNAME} method)
	if [ -z "${METHOD}" -o "${METHOD}" = "-" ]; then
		METHOD="ftp"
		jset ${JAILNAME} method ${METHOD}
	fi
	msg "Upgrading using ${METHOD}"
	case ${METHOD} in
	ftp|ftp-archive)
		MASTERMNT=$(jget ${JAILNAME} mnt)
		MASTERNAME=${JAILNAME}
		jstart 1
		if [ -z "${TORELEASE}" ]; then
			injail /usr/sbin/freebsd-update fetch install
		else
			yes | injail env PAGER=/bin/cat /usr/sbin/freebsd-update -r ${TORELEASE} upgrade install ||
				err 1 "Fail to upgrade system"
			yes | injail env PAGER=/bin/cat /usr/sbin/freebsd-update install ||
				err 1 "Fail to upgrade system"
			jset ${JAILNAME} version ${TORELEASE}
		fi
		jstop
		markfs clean ${JAILMNT}
		;;
	csup)
		install_from_csup
................................................................................
		unset CCACHE_TEMPDIR
	fi

	msg "Starting make buildworld with ${PARALLEL_JOBS} jobs"
	make -C ${JAILMNT}/usr/src buildworld ${MAKE_JOBS} ${MAKEWORLDARGS} || err 1 "Fail to build world"
	msg "Starting make installworld"
	make -C ${JAILMNT}/usr/src installworld DESTDIR=${JAILMNT} || err 1 "Fail to install world"
	make -C ${JAILMNT}/usr/src DESTDIR=${JAILMNT} distrib-dirs &&
	make -C ${JAILMNT}/usr/src DESTDIR=${JAILMNT} distribution
}

install_from_svn() {
	local UPDATE=0
	local proto
	[ -d ${JAILMNT}/usr/src ] && UPDATE=1
................................................................................
	svn+https) proto="https" ;;
	svn+ssh) proto="svn+ssh" ;;
	svn+file) proto="file" ;;
	svn) proto="svn" ;;
	esac
	if [ ${UPDATE} -eq 0 ]; then
		msg_n "Checking out the sources from svn..."
		svn -q co ${proto}://${SVN_HOST}/base/${VERSION} ${JAILMNT}/usr/src || err 1 " fail"
		echo " done"
		if [ -n "${SRCPATCHFILE}" ]; then
			msg_n "Patching the sources with ${SRCPATCHFILE}"
			svn -q patch ${SRCPATCHFILE} ${JAILMNT}/usr/src || err 1 " fail"
			echo done
		fi
	else
		msg_n "Updating the sources from svn..."
		svn -q update ${JAILMNT}/usr/src || err 1 " fail"
		echo " done"
	fi
	build_and_install_world
}

install_from_csup() {
	local UPDATE=0
................................................................................
}

install_from_ftp() {
	mkdir ${JAILMNT}/fromftp
	local URL V

	V=${ALLBSDVER:-${VERSION}}
	case $V in
	[0-4].*) HASH=MD5 ;;
	5.[0-4]*) HASH=MD5 ;;
	*) HASH=SHA256 ;;
	esac
	if [ ${V%%.*} -lt 9 ]; then
		msg "Fetching sets for FreeBSD ${V} ${ARCH}"
		case ${METHOD} in
		ftp|gjb)
			case ${VERSION} in
				*-PRERELEASE|*-STABLE) type=snapshots ;;
				*) type=releases ;;
................................................................................
			echo ${FREEBSD_HOST} | egrep -E "(_PROTO_|_CHANGE_THIS_)" > /dev/null
			if [ $? -eq 0 ]; then
				msg "FREEBSD_HOST from config invalid; defaulting to http://ftp.freebsd.org"
				FREEBSD_HOST="http://ftp.freebsd.org"
			fi
			URL="${FREEBSD_HOST}/pub/FreeBSD/${type}/${ARCH}/${V}" ;;
		allbsd) URL="https://pub.allbsd.org/FreeBSD-snapshots/${ARCH}-${ARCH}/${V}-JPSNAP/ftp" ;;
		ftp-archive) URL="ftp://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/${ARCH}/${V}" ;;
		esac
		DISTS="base dict src games"
		[ ${ARCH} = "amd64" ] && DISTS="${DISTS} lib32"
		for dist in ${DISTS}; do
			fetch_file ${JAILMNT}/fromftp/ ${URL}/$dist/CHECKSUM.${HASH} ||
				err 1 "Fail to fetch checksum file"
			sed -n "s/.*(\(.*\...\)).*/\1/p" \
				${JAILMNT}/fromftp/CHECKSUM.${HASH} | \
				while read pkg; do
				[ ${pkg} = "install.sh" ] && continue
				# Let's retry at least one time
				fetch_file ${JAILMNT}/fromftp/ ${URL}/${dist}/${pkg}
			done
		done

................................................................................
				s*)
					APPEND="usr/src"
					;;
				*)
					APPEND=""
					;;
			esac
			(cat ${JAILMNT}/fromftp/${SET}.* || echo Error) | \
				tar --unlink -xpf - -C ${JAILMNT}/${APPEND} || err 1 " fail"
			echo " done"
		done
	else
		local type
		case ${METHOD} in
			ftp|gjb|ftp-archive)
				case ${VERSION} in
					*-CURRENT|*-PRERELEASE|*-STABLE) type=snapshots ;;
					*) type=releases ;;
				esac

				# Check that the defaults have been changed
				echo ${FREEBSD_HOST} | egrep -E "(_PROTO_|_CHANGE_THIS_)" > /dev/null
................................................................................
		esac
		DISTS="base.txz src.txz games.txz"
		[ ${ARCH} = "amd64" ] && DISTS="${DISTS} lib32.txz"
		for dist in ${DISTS}; do
			msg "Fetching ${dist} for FreeBSD ${V} ${ARCH}"
			fetch_file ${JAILMNT}/fromftp/${dist} ${URL}/${dist}
			msg_n "Extracting ${dist}..."
			tar -xpf ${JAILMNT}/fromftp/${dist} -C  ${JAILMNT}/ || err 1 " fail"
			echo " done"
		done
	fi

	msg_n "Cleaning up..."
	rm -rf ${JAILMNT}/fromftp/
	echo " done"
}

create_jail() {
	jail_exists ${JAILNAME} && err 2 "The jail ${JAILNAME} already exists"

	test -z ${VERSION} && usage

	[ "${JAILNAME#*.*}" = "${JAILNAME}" ] ||
		err 1 "The jailname can not contain a period (.). See jail(8)"

	if [ -z ${JAILMNT} ]; then
		[ -z ${BASEFS} ] && err 1 "Please provide a BASEFS variable in your poudriere.conf"
		JAILMNT=${BASEFS}/jails/${JAILNAME}
	fi

	if [ -z ${JAILFS} ]; then
		[ -z ${ZPOOL} ] && err 1 "Please provide a ZPOOL variable in your poudriere.conf"
		JAILFS=${ZPOOL}${ZROOTFS}/jails/${JAILNAME}
	fi

	case ${METHOD} in
	ftp|gjb|ftp-archive)
		FCT=install_from_ftp
		;;





	allbsd)
		FCT=install_from_ftp
		ALLBSDVER=`fetch -qo - \
			https://pub.allbsd.org/FreeBSD-snapshots/${ARCH}-${ARCH}/ | \
			sed -n "s,.*href=\"\(.*${VERSION}.*\)-JPSNAP/\".*,\1,p" | \
			sort -k 3 -t - -r | head -n 1 `

		[ -z ${ALLBSDVER} ] && err 1 "Unknown version $VERSION"


		OIFS=${IFS}
		IFS=-
		set -- ${ALLBSDVER}
		IFS=${OIFS}
		RELEASE="${ALLBSDVER}-JPSNAP/ftp"
		;;
................................................................................
	svn*)
		SVN=`which svn`
		test -z ${SVN} && err 1 "You need svn on your host to use svn method"
		case ${VERSION} in
			stable/*![0-9]*)
				err 1 "bad version number for stable version"
				;;
			head@*![0-9]*)
				err 1 "bad revision number for head version"
				;;
			release/*![0-9]*.[0-9].[0-9])
				err 1 "bad version number for release version"
				;;
			releng/*![0-9]*.[0-9])
				err 1 "bad version number for releng version"
				;;
			stable/*|head*|release/*|releng/*.[0-9]) ;;
			*)
				err 1 "version with svn should be: head[@rev] or stable/N or release/N or releng/N"
				;;
		esac
		FCT=install_from_svn
		;;
	csup)
		case ${VERSION} in
			.)
................................................................................
	${FCT}

	eval `grep "^[RB][A-Z]*=" ${JAILMNT}/usr/src/sys/conf/newvers.sh `
	RELEASE=${REVISION}-${BRANCH}
	jset ${JAILNAME} version ${RELEASE}
	update_version ${RELEASE}

	if [ "${ARCH}" = "i386" -a "${REALARCH}" = "amd64" ]; then
		cat > ${JAILMNT}/etc/make.conf << EOF
ARCH=i386
MACHINE=i386
MACHINE_ARCH=i386
EOF

	fi
................................................................................
PTNAME=default
SETNAME=""

SCRIPTPATH=`realpath $0`
SCRIPTPREFIX=`dirname ${SCRIPTPATH}`
. ${SCRIPTPREFIX}/common.sh

while getopts "J:j:v:a:z:m:n:f:M:sdklqcip:ut:z:P:" FLAG; do
	case "${FLAG}" in
		j)
			JAILNAME=${OPTARG}
			;;
		J)
			PARALLEL_JOBS=${OPTARG}
			;;
		v)
			VERSION=${OPTARG}
			;;
		a)
			[ "${REALARCH}" != "amd64" -a "${REALARCH}" != ${OPTARG} ] &&
				err 1 "Only amd64 host can choose another architecture"

			ARCH=${OPTARG}
			;;
		m)
			METHOD=${OPTARG}
			;;
		f)
			JAILFS=${OPTARG}
................................................................................
			;;
		d)
			DELETE=1
			;;
		p)
			PTNAME=${OPTARG}
			;;
		P)
			[ -f ${OPTARG} ] || err 1 "No such patch"
			SRCPATCHFILE=${OPTARG}
			;;
		q)
			QUIET=1
			;;
		u)
			UPDATE=1
			;;
		t)
................................................................................
		*)
			usage
			;;
	esac
done

METHOD=${METHOD:-ftp}
if [ -n "${JAILNAME}" -a ${CREATE} -eq 0 ]; then
	ARCH=$(jget ${JAILNAME} arch)
	JAILFS=$(jget ${JAILNAME} fs)
	JAILMNT=$(jget ${JAILNAME} mnt)
fi




case "${CREATE}${LIST}${STOP}${START}${DELETE}${UPDATE}" in
	100000)
		test -z ${JAILNAME} && usage
		create_jail
		;;
	010000)
		list_jail
................................................................................
		test -z ${JAILNAME} && usage
		delete_jail
		;;
	000001)
		test -z ${JAILNAME} && usage
		update_jail
		;;
	*)
		usage
		;;
esac

Changes to src/share/poudriere/options.sh.

102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119

export PORTSDIR=`pget ${PTNAME} mnt`
[ -d "${PORTSDIR}/ports" ] && PORTSDIR="${PORTSDIR}/ports"
[ -z "${PORTSDIR}" ] && err 1 "No such ports tree: ${PTNAME}"

if [ $# -eq 0 ]; then
	[ -n "${BULK_LIST}" ] || err 1 "No packages specified"
	test -f ${BULK_LIST} || err 1 "No such list of packages: ${BULK_LIST}"
LISTPORTS=`grep -v -E '(^[[:space:]]*#|^[[:space:]]*$)' ${BULK_LIST}`
else

	[ -z "${BULK_LIST}" ] || err 1 "command line arguments and list of ports cannot be used at the same time"
	LISTPORTS="$@"
fi

PORT_DBDIR=${SCRIPTPREFIX}/../../etc/poudriere.d/${JAILNAME}${JAILNAME:+-}${SETNAME}${SETNAME:+-}options

mkdir -p ${PORT_DBDIR}








|


>
|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

export PORTSDIR=`pget ${PTNAME} mnt`
[ -d "${PORTSDIR}/ports" ] && PORTSDIR="${PORTSDIR}/ports"
[ -z "${PORTSDIR}" ] && err 1 "No such ports tree: ${PTNAME}"

if [ $# -eq 0 ]; then
	[ -n "${BULK_LIST}" ] || err 1 "No packages specified"
	[ -f ${BULK_LIST} ] || err 1 "No such list of packages: ${BULK_LIST}"
LISTPORTS=`grep -v -E '(^[[:space:]]*#|^[[:space:]]*$)' ${BULK_LIST}`
else
	[ -z "${BULK_LIST}" ] ||
		err 1 "command line arguments and list of ports cannot be used at the same time"
	LISTPORTS="$@"
fi

PORT_DBDIR=${SCRIPTPREFIX}/../../etc/poudriere.d/${JAILNAME}${JAILNAME:+-}${SETNAME}${SETNAME:+-}options

mkdir -p ${PORT_DBDIR}

Changes to src/share/poudriere/ports.sh.

35
36
37
38
39
40
41

42
43
44
45
46
47
48
..
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
..
97
98
99
100
101
102
103



104
105
106
107
108
109
110
...
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
...
202
203
204
205
206
207
208





209
210
211
212

213
214
215
216
217
218
219
220

Parameters:
    -c            -- create a portstree
    -d            -- delete a portstree
    -u            -- update a portstree
    -l            -- lists all available portstrees
    -q            -- quiet (remove the header in list)


Options:
    -F            -- when used with -c, only create the needed ZFS
                     filesystems and directories, but do not populate
                     them.
    -p name       -- specifies the name of the portstree we workon . If not
                     specified, work on a portstree called \"default\".
................................................................................

CREATE=0
FAKE=0
UPDATE=0
DELETE=0
LIST=0
QUIET=0

BRANCH=head
while getopts "B:cFudlp:qf:M:m:" FLAG; do
	case "${FLAG}" in
		B)
			BRANCH="${OPTARG}"
			;;
		c)
			CREATE=1
			;;
................................................................................
			;;
		M)
			PTMNT=${OPTARG}
			;;
		m)
			METHOD=${OPTARG}
			;;



		*)
			usage
		;;
	esac
done

[ $(( CREATE + UPDATE + DELETE + LIST )) -lt 1 ] && usage
................................................................................
svn);;
git);;
*) usage;;
esac

if [ ${LIST} -eq 1 ]; then
	format='%-20s %-10s %s\n'
	[ $QUIET -eq 0 ] && \
		printf "${format}" "PORTSTREE" "METHOD" "PATH"
	porttree_list | while read ptname ptmethod ptpath; do
		printf "${format}" ${ptname} ${ptmethod} ${ptpath}
	done
else
	test -z "${PTNAME}" && usage
fi







if [ ${CREATE} -eq 1 ]; then
	# test if it already exists
	porttree_exists ${PTNAME} && err 2 "The ports tree ${PTNAME} already exists"
	: ${PTMNT="${BASEFS:=/usr/local${ZROOTFS}}/ports/${PTNAME}"}
	: ${PTFS="${ZPOOL}${ZROOTFS}/ports/${PTNAME}"}





	createfs ${PTNAME} ${PTMNT} ${PTFS}
	pset ${PTNAME} mnt ${PTMNT}
	if [ $FAKE -eq 0 ]; then
		case ${METHOD} in
		portsnap)
			mkdir ${PTMNT}/.snap
			msg "Extracting portstree \"${PTNAME}\"..."
			/usr/sbin/portsnap -d ${PTMNT}/.snap -p ${PTMNT} fetch extract || \
			/usr/sbin/portsnap -d ${PTMNT}/.snap -p ${PTMNT} fetch extract || \
			{
				destroyfs ports ${PTNAME}
				err 1 " Fail"
			}
			;;
		svn*)
			case ${METHOD} in
			svn+http) proto="http" ;;
			svn+https) proto="https" ;;
			svn+ssh) proto="svn+ssh" ;;
			svn+file) proto="file" ;;
			svn) proto="svn" ;;
			esac

			msg_n "Checking out the ports tree..."

			svn -q co ${proto}://${SVN_HOST}/ports/${BRANCH} \
				${PTMNT} || {
					destroyfs ports ${PTNAME}
					err 1 " Fail"
				}
			echo " done"
			;;
		git)
			msg "Cloning the ports tree"
			git clone ${GIT_URL} ${PTMNT} || {
				destroyfs ports ${PTNAME}
				err 1 " Fail"
			}
			echo " done"
			;;
		esac
		pset ${PTNAME} method ${METHOD}


	fi


fi

if [ ${DELETE} -eq 1 ]; then
	porttree_exists ${PTNAME} || err 2 "No such ports tree ${PTNAME}"
	PTMNT=$(pget ${PTNAME} mnt)
	[ -d "${PTMNT}/ports" ] && PORTSMNT="${PTMNT}/ports"
	/sbin/mount -t nullfs | /usr/bin/grep -q "${PORTSMNT:-${PTMNT}} on" \
		&& err 1 "Ports tree \"${PTNAME}\" is currently mounted and being used."
	msg_n "Deleting portstree \"${PTNAME}\""
	destroyfs ports ${PTNAME}

	echo " done"
fi

if [ ${UPDATE} -eq 1 ]; then
	porttree_exists ${PTNAME} || err 2 "No such ports tree ${PTNAME}"
	METHOD=$(pget ${PTNAME} method)
	PTMNT=$(pget ${PTNAME} mnt)
................................................................................
	msg "Updating portstree \"${PTNAME}\""
	if [ -z "${METHOD}" -o ${METHOD} = "-" ]; then
		METHOD=portsnap
		pset ${PTNAME} method ${METHOD}
	fi
	case ${METHOD} in
	portsnap|"")





		/usr/sbin/portsnap -d ${PTMNT}/.snap -p ${PORTSMNT:-${PTMNT}} ${PSCOMMAND} alfred
		;;
	svn*)
		msg_n "Updating the ports tree..."

		svn -q update ${PORTSMNT:-${PTMNT}}
		echo " done"
		;;
	git)
		msg "Pulling from ${GIT_URL}"
		cd ${PORTSMNT:-${PTMNT}} && git pull
		echo " done"
		;;







>







 







>

|







 







>
>
>







 







|





|

>
>
>
>
>
>
>





>
>
>
>
>







|
|
<
<
|
<











>
|
|
<
<
<




|
<
<
<




>
>

>
>









|
>







 







>
>
>
>
>
|



>
|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
..
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
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
...
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

Parameters:
    -c            -- create a portstree
    -d            -- delete a portstree
    -u            -- update a portstree
    -l            -- lists all available portstrees
    -q            -- quiet (remove the header in list)
    -v            -- Be verbose; show more information.

Options:
    -F            -- when used with -c, only create the needed ZFS
                     filesystems and directories, but do not populate
                     them.
    -p name       -- specifies the name of the portstree we workon . If not
                     specified, work on a portstree called \"default\".
................................................................................

CREATE=0
FAKE=0
UPDATE=0
DELETE=0
LIST=0
QUIET=0
VERBOSE=0
BRANCH=head
while getopts "B:cFudlp:qf:M:m:v" FLAG; do
	case "${FLAG}" in
		B)
			BRANCH="${OPTARG}"
			;;
		c)
			CREATE=1
			;;
................................................................................
			;;
		M)
			PTMNT=${OPTARG}
			;;
		m)
			METHOD=${OPTARG}
			;;
		v)
			VERBOSE=$((${VERBOSE:-0} + 1))
			;;
		*)
			usage
		;;
	esac
done

[ $(( CREATE + UPDATE + DELETE + LIST )) -lt 1 ] && usage
................................................................................
svn);;
git);;
*) usage;;
esac

if [ ${LIST} -eq 1 ]; then
	format='%-20s %-10s %s\n'
	[ $QUIET -eq 0 ] &&
		printf "${format}" "PORTSTREE" "METHOD" "PATH"
	porttree_list | while read ptname ptmethod ptpath; do
		printf "${format}" ${ptname} ${ptmethod} ${ptpath}
	done
else
	[ -z "${PTNAME}" ] && usage
fi

cleanup_new_ports() {
	msg "Error while creating ports tree, cleaning up." >&2
	destroyfs ${PTMNT} ports
	rm -rf ${POUDRIERED}/ports/${PTNAME} || :
}

if [ ${CREATE} -eq 1 ]; then
	# test if it already exists
	porttree_exists ${PTNAME} && err 2 "The ports tree ${PTNAME} already exists"
	: ${PTMNT="${BASEFS:=/usr/local${ZROOTFS}}/ports/${PTNAME}"}
	: ${PTFS="${ZPOOL}${ZROOTFS}/ports/${PTNAME}"}

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

	createfs ${PTNAME} ${PTMNT} ${PTFS}
	pset ${PTNAME} mnt ${PTMNT}
	if [ $FAKE -eq 0 ]; then
		case ${METHOD} in
		portsnap)
			mkdir ${PTMNT}/.snap
			msg "Extracting portstree \"${PTNAME}\"..."
			/usr/sbin/portsnap -d ${PTMNT}/.snap -p ${PTMNT} fetch extract ||
			/usr/sbin/portsnap -d ${PTMNT}/.snap -p ${PTMNT} fetch extract ||


			    err 1 " fail"

			;;
		svn*)
			case ${METHOD} in
			svn+http) proto="http" ;;
			svn+https) proto="https" ;;
			svn+ssh) proto="svn+ssh" ;;
			svn+file) proto="file" ;;
			svn) proto="svn" ;;
			esac

			msg_n "Checking out the ports tree..."
			[ ${VERBOSE} -gt 0 ] || quiet="-q"
			svn ${quiet} co ${proto}://${SVN_HOST}/ports/${BRANCH} \
				${PTMNT} || err 1 " fail"



			echo " done"
			;;
		git)
			msg "Cloning the ports tree"
			git clone ${GIT_URL} ${PTMNT} || err 1 " fail"



			echo " done"
			;;
		esac
		pset ${PTNAME} method ${METHOD}
	else
		pset ${PTNAME} method "-"
	fi

	unset CLEANUP_HOOK
fi

if [ ${DELETE} -eq 1 ]; then
	porttree_exists ${PTNAME} || err 2 "No such ports tree ${PTNAME}"
	PTMNT=$(pget ${PTNAME} mnt)
	[ -d "${PTMNT}/ports" ] && PORTSMNT="${PTMNT}/ports"
	/sbin/mount -t nullfs | /usr/bin/grep -q "${PORTSMNT:-${PTMNT}} on" \
		&& err 1 "Ports tree \"${PTNAME}\" is currently mounted and being used."
	msg_n "Deleting portstree \"${PTNAME}\""
	destroyfs ${PTMNT} ports
	rm -rf ${POUDRIERED}/ports/${PTNAME} || :
	echo " done"
fi

if [ ${UPDATE} -eq 1 ]; then
	porttree_exists ${PTNAME} || err 2 "No such ports tree ${PTNAME}"
	METHOD=$(pget ${PTNAME} method)
	PTMNT=$(pget ${PTNAME} mnt)
................................................................................
	msg "Updating portstree \"${PTNAME}\""
	if [ -z "${METHOD}" -o ${METHOD} = "-" ]; then
		METHOD=portsnap
		pset ${PTNAME} method ${METHOD}
	fi
	case ${METHOD} in
	portsnap|"")
		if [ -d "${PTMNT}/snap" ]; then
			SNAPDIR=${PTMNT}/snap
		else
			SNAPDIR=${PTMNT}/.snap
		fi
		/usr/sbin/portsnap -d ${SNAPDIR} -p ${PORTSMNT:-${PTMNT}} ${PSCOMMAND} alfred
		;;
	svn*)
		msg_n "Updating the ports tree..."
		[ ${VERBOSE} -gt 0 ] || quiet="-q"
		svn ${quiet} update ${PORTSMNT:-${PTMNT}}
		echo " done"
		;;
	git)
		msg "Pulling from ${GIT_URL}"
		cd ${PORTSMNT:-${PTMNT}} && git pull
		echo " done"
		;;

Changes to src/share/poudriere/queue.sh.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 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.
set -e

usage() {
        echo "poudriere queue queuename poudriere_command"
	exit 1
}

SCRIPTPATH=`realpath $0`
SCRIPTPREFIX=`dirname ${SCRIPTPATH}`
. ${SCRIPTPREFIX}/common.sh








|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 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.
set -e

usage() {
	echo "poudriere queue queuename poudriere_command"
	exit 1
}

SCRIPTPATH=`realpath $0`
SCRIPTPREFIX=`dirname ${SCRIPTPATH}`
. ${SCRIPTPREFIX}/common.sh

Changes to src/share/poudriere/testport.sh.

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
...
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
...
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
			;;
		*)
			usage
			;;
	esac
done

test -z ${ORIGIN} && usage

export SKIPSANITY

test -z "${JAILNAME}" && err 1 "Don't know on which jail to run please specify -j"

MASTERNAME=${JAILNAME}-${PTNAME}${SETNAME:+-${SETNAME}}
MASTERMNT=${POUDRIERE_DATA}/build/${MASTERNAME}/ref
export MASTERNAME
export MASTERMNT
export POUDRIERE_BUILD_TYPE=bulk

................................................................................
	msg "Depends failed to build"
	msg "Failed ports: ${failed}"
	[ -n "${skipped}" ] && 	msg "Skipped ports: ${skipped}"

	exit 1
fi

bset status "depends:"

unmarkfs prepkg ${MASTERMNT}

injail make -C /usr/ports/${ORIGIN} pkg-depends extract-depends \
	fetch-depends patch-depends build-depends lib-depends

bset status "testing:"

PKGNAME=`injail make -C /usr/ports/${ORIGIN} -VPKGNAME`
LOCALBASE=`injail make -C /usr/ports/${ORIGIN} -VLOCALBASE`
: ${PREFIX:=$(injail make -C /usr/ports/${ORIGIN} -VPREFIX)}
if [ "${USE_PORTLINT}" = "yes" ]; then

	[ ! -x `which portlint` ] && err 2 "First install portlint if you want USE_PORTLINT to work as expected"
	msg "Portlint check"
	set +e

	cd ${MASTERMNT}/usr/ports/${ORIGIN} && PORTSDIR="${MASTERMNT}/usr/ports" portlint -C | tee ${log}/logs/${PKGNAME}.portlint.log

	set -e
fi
[ ${NOPREFIX} -ne 1 ] && PREFIX="${BUILDROOT:-/prefix}/`echo ${PKGNAME} | tr '[,+]' _`"
PORT_FLAGS="NO_DEPENDS=yes PREFIX=${PREFIX}"
msg "Building with flags: ${PORT_FLAGS}"

if [ -d ${MASTERMNT}${PREFIX} ]; then
................................................................................

	save_wrkdir ${MASTERMNT} "${PKGNAME}" "/usr/ports/${ORIGIN}" "${failed_phase}" || :

	if [ ${INTERACTIVE_MODE} -eq 0 ]; then
		stop_build /usr/ports/${ORIGIN} ${log}/logs/${PKGNAME}.log
		exit 1
	fi


fi

msg "Installing from package"
injail ${PKG_ADD} /tmp/pkgs/${PKGNAME}.${PKG_EXT}

# Interactive test mode
if [ $INTERACTIVE_MODE -gt 0 ]; then
	print_phase_header "Interactive"

	msg "Installing run-depends"
	# Install run-depends since this is an interactive test
	echo "PACKAGES=/packages" >> ${MASTERMNT}/etc/make.conf
	injail make -C /usr/ports/${ORIGIN} run-depends || \
		msg "Failed to install RUN_DEPENDS"

	# Enable networking
	jstop
	jstart 1

	if [ $INTERACTIVE_MODE -eq 1 ]; then







|



|







 







<
<


<
<
<






>
|


>
|
>







 







>
>












|







95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
...
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
...
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
			;;
		*)
			usage
			;;
	esac
done

[ -z ${ORIGIN} ] && usage

export SKIPSANITY

[ -z "${JAILNAME}" ] && err 1 "Don't know on which jail to run please specify -j"

MASTERNAME=${JAILNAME}-${PTNAME}${SETNAME:+-${SETNAME}}
MASTERMNT=${POUDRIERE_DATA}/build/${MASTERNAME}/ref
export MASTERNAME
export MASTERMNT
export POUDRIERE_BUILD_TYPE=bulk

................................................................................
	msg "Depends failed to build"
	msg "Failed ports: ${failed}"
	[ -n "${skipped}" ] && 	msg "Skipped ports: ${skipped}"

	exit 1
fi



unmarkfs prepkg ${MASTERMNT}




bset status "testing:"

PKGNAME=`injail make -C /usr/ports/${ORIGIN} -VPKGNAME`
LOCALBASE=`injail make -C /usr/ports/${ORIGIN} -VLOCALBASE`
: ${PREFIX:=$(injail make -C /usr/ports/${ORIGIN} -VPREFIX)}
if [ "${USE_PORTLINT}" = "yes" ]; then
	[ ! -x `which portlint` ] &&
		err 2 "First install portlint if you want USE_PORTLINT to work as expected"
	msg "Portlint check"
	set +e
	cd ${MASTERMNT}/usr/ports/${ORIGIN} &&
		PORTSDIR="${MASTERMNT}/usr/ports" portlint -C | \
		tee ${log}/logs/${PKGNAME}.portlint.log
	set -e
fi
[ ${NOPREFIX} -ne 1 ] && PREFIX="${BUILDROOT:-/prefix}/`echo ${PKGNAME} | tr '[,+]' _`"
PORT_FLAGS="NO_DEPENDS=yes PREFIX=${PREFIX}"
msg "Building with flags: ${PORT_FLAGS}"

if [ -d ${MASTERMNT}${PREFIX} ]; then
................................................................................

	save_wrkdir ${MASTERMNT} "${PKGNAME}" "/usr/ports/${ORIGIN}" "${failed_phase}" || :

	if [ ${INTERACTIVE_MODE} -eq 0 ]; then
		stop_build /usr/ports/${ORIGIN} ${log}/logs/${PKGNAME}.log
		exit 1
	fi
elif [ -f ${MASTERMNT}/usr/ports/${ORIGIN}/.keep ]; then
	save_wrkdir ${MASTERMNT} "${PKGNAME}" "/usr/ports/${ORIGIN}" "noneed" ||:
fi

msg "Installing from package"
injail ${PKG_ADD} /tmp/pkgs/${PKGNAME}.${PKG_EXT}

# Interactive test mode
if [ $INTERACTIVE_MODE -gt 0 ]; then
	print_phase_header "Interactive"

	msg "Installing run-depends"
	# Install run-depends since this is an interactive test
	echo "PACKAGES=/packages" >> ${MASTERMNT}/etc/make.conf
	injail make -C /usr/ports/${ORIGIN} run-depends ||
		msg "Failed to install RUN_DEPENDS"

	# Enable networking
	jstop
	jstart 1

	if [ $INTERACTIVE_MODE -eq 1 ]; then

Changes to zsh-completions.

23
24
25
26
27
28
29

30
31

32
33
34
35

36
37
38
39
40
41
42
..
94
95
96
97
98
99
100

101
102
103
104
105
106
107
  return ret
}

_bulk=(
	'-a[Build all ports in the tree]'
	'-B[What buildname to use]:buildname'
	'-f[Give the list of ports to build]:name of file:_files'

	'-c[Clean the previous built binary packages]'
	'-C[Clean previous packages for the given list to build]'

	'-t[Add some testings to package building]'
	'-s[Skip sanity]'
	'-j[Run only on the given jail]::jail name:_poudriere_jail'
	'-p[Specify on which ports tree the bulk will be done]::tree:_poudriere_pt'

	'-J[Specify the number of jobs you want to run in parallel]::'
	'-R[Remove RESTRICTED packages after building]'
	'-v[Be verbose; show more information. Specify twice to enable debug output.]'
	'-z[Specify on which SET to use]::'
)

_jail=(
................................................................................
	'(-c -d -u)-l[lists all available portstrees]'
	'-q[quiet (remove the header in list)]'
	'-F[when used with -c, only create the needed ZFS filesystems and directories, but do not populate them]'
	'-p[specify the name of the portstree we work on]::tree:_poudriere_pt'
	'-f[FS name (tank/jails/myjail)]::fs:_files -/'
	'-M[mountpoint]::mountpoint:_files -/'
	'-m[method]::method:((portsnap svn svn+http svn+ssh git))'

)

_poudriere () {
	local cmds
	local context state line
	typeset -A val_args
	cmds=(







>


>




>







 







>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
  return ret
}

_bulk=(
	'-a[Build all ports in the tree]'
	'-B[What buildname to use]:buildname'
	'-f[Give the list of ports to build]:name of file:_files'
	'-F[Only fetch from original master_sites; skip FreeBSD mirrors]'
	'-c[Clean the previous built binary packages]'
	'-C[Clean previous packages for the given list to build]'
	'-N[Do not build repository or INDEX when done building]'
	'-t[Add some testings to package building]'
	'-s[Skip sanity]'
	'-j[Run only on the given jail]::jail name:_poudriere_jail'
	'-p[Specify on which ports tree the bulk will be done]::tree:_poudriere_pt'
	'-T[Try building BROKEN ports]'
	'-J[Specify the number of jobs you want to run in parallel]::'
	'-R[Remove RESTRICTED packages after building]'
	'-v[Be verbose; show more information. Specify twice to enable debug output.]'
	'-z[Specify on which SET to use]::'
)

_jail=(
................................................................................
	'(-c -d -u)-l[lists all available portstrees]'
	'-q[quiet (remove the header in list)]'
	'-F[when used with -c, only create the needed ZFS filesystems and directories, but do not populate them]'
	'-p[specify the name of the portstree we work on]::tree:_poudriere_pt'
	'-f[FS name (tank/jails/myjail)]::fs:_files -/'
	'-M[mountpoint]::mountpoint:_files -/'
	'-m[method]::method:((portsnap svn svn+http svn+ssh git))'
	'-v[Be verbose; show more information.]'
)

_poudriere () {
	local cmds
	local context state line
	typeset -A val_args
	cmds=(