· 7 years ago · Mar 01, 2019, 05:28 PM
1#!/bin/bash +x
2#
3# The primary useful functions are:
4# `srpmAutoBuild_build <...>`; where `<...>` can be a (list of) spec-file(s) and/or srpm(s). This function does "most of the work", including installing build dependencies and actually building the SRPMs.
5# `srpmAutoBuild_ALL`, which scripts the entire "find new SRPMs / download them / setup + enter mock / install build dependencies / build SRPMs into RPMs" process. This allows for a single command to run everything. There are several flags to control the behavior of this function (see help text in function header)
6#
7# To use the packages in a local repository with dnf, run `localrepo_setupDNF` to setup the repo and `localrepo_updateDatabase` to update its database with new packages.
8#
9# This is basically intended as a replacement for `dnf update` but for SRPMs, where it downloads and builds SRPMs rather than downloads and installs the pre-compiled RPMs
10#
11# Lists of files can use globs, and you can mix-and-match specs and srpms. Build dependencies will automatically be installed;
12# and several common but harmless rpm build errors are automatically dealt with, resulting in a very high build success rate
13# (though this comes at the cost of needlessly re-trying to build some packages that need manual attention prior to being built - packages will be
14# built up to 4 times with various tweaks applied, and will always follow the same workflow regardless of what the cause of the error was).
15#
16# These functions are designed to work with mock, but should (mostly) work in a standard OS environment too.. However, to accommodate the `mock` environment
17# (which doesnt necessarily have `sudo`) you will need to be root to successfully run many of these functions. They wont call `sudo` on their own, however, most will check whether you are root or not and prompt you to re-call the command as root automatically (this fetches the last command recorded in the history and re-calls it using `su`)
18#
19# Building in a mock environment is recommended. To do this, use `srpmAutoBuild_mock-chroot`./ This will run the commands given to it (non-interactively) in mock, --OR-- if no inputs are used it will drop you into an (interactive) mock chroot shell.
20#
21#
22# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
23# # # # # # # # # # # # # # # # # # # # # # # # # # # ----- EXAMPLE USAGE ----- # # # # # # # # # # # # # # # # # # # # # # # # # # #
24# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
25#
26# -----> EASY MODE:
27#
28# `srpmAutoBuild_ALL`: this *should* do literally everything related to downloading/building SRPMs for you automatically (assuming you want to rebuild EVERY rpm that you have currently installed and that has an available SRPM). several flags are available (run `srpmAutoBuild_help srpmAutoBuild_ALL` for more info)
29#
30# To use the rpms you built in a local repository with dnf, run `localrepo_setupDNF` to setup the repository and then run `localrepo_updateDatabase` to update whenever you have built new RPMs. To automatically install the just built rpms and update the repository, add '+r' to the end off one of the install flags (e.g., `srpmAutoBuild_ALL -i+r`)
31#
32# To fully automate all aspects of downloading SRPMs, installing dependencies, building them, and cleanup.
33# This is intended to be a function that is roughly equivalent to `dnf upgrade`, except it downloads and builds SRPMs rather than download and install pre-compiled RPMs
34#
35#
36# -----> MORE DETAIL:
37#
38# `srpmAutoBuild_ALL` more-or-less automates the following workflow. Actual commands are shown below.
39#
40# # (1) source srpmAutoBuild.sh,
41# # (2) Get RPM / MOCK dir paths
42# # (3) initialize mock;
43# # (4) download [all available] SRPMs into Mock,
44# # (5) enter mock chroot,
45# # (6) setup environment variables from inside of mock;
46# # (7) download / install all build dependencies for the SRPMs and build the SRPM packages (first into SPEC-files, then into RPMs),
47# # (7a) OPTIONAL: repeat (5-7) and start a 2nd build run that processes packages in the opposite order (use -r Flag with srpmAutoBuild_build )
48# # (8) exit the mock chroot, and
49# # (9) transfer all packages built in the mock chroot to ${LOCALREPO_DIR} and cleanup the mock environment.
50#
51#
52# ---------------------------------------------- PREP - SETUP MOCK AND GET SRPMS ----------------------------------------------
53#
54# source /usr/local/bin/my-scripts/srpmAutoBuild.sh # Source srpmAutoBuild package
55# srpmAutoBuild_mock-init # clean + [re]initialize + setup the mock environment
56# srpmAutoBuild_mock-downloadSRPMs # download SRPMs into Mock for all potential build able SRPMSs automatically
57# cd ${RPM_BUILD_DIR}/SRPMS && dnf download --source <...> # ALT: download only select SRPMS
58#
59#
60# ---------------------------------------------- BUILD - RUN COMMANDS INSIDE OF MOCK ----------------------------------------------
61#
62# srpmAutoBuild_mock-chroot # enter mock chroot.
63# srpmAutoBuild_rpmAutoBuild_build ${RPM_BUILD_DIR}/SRPMS/* [&] # build SRPMs and/or SPECs. This function does most of the work. Fork this if you also want to run the 2nd build from the same terminal.
64# srpmAutoBuild_rpmAutoBuild_build --REVERSE ${RPM_BUILD_DIR}/SRPMS/* [&] # OPTIONAL: 2nd build run going in reverse order
65# exit
66#
67# ----- OR -----
68#
69# srpmAutoBuild_generateBuildScripts # generates 2 script files to automate the build process: [${MOCK_ROOT_DIR}]/build-[main|secondary].sh.
70# srpmAutoBuild_mock-chroot # enter mock chroot.
71# /build-main.sh [&] # this basically does the same thing that the commands above do
72# /build-secondary.sh [&] # OPTIONAL: 2nd build run going in reverse order
73# exit
74#
75# ----- OR -----
76#
77# srpmAutoBuild_generateBuildScripts # generates 2 script files to automate the build process: [${MOCK_ROOT_DIR}]/build-[main|secondary].sh.
78# srpmAutoBuild_mock-chroot '/build-main.sh' [&] # runs /build-main.sh in mock non-interactively from a shell OUTSIDE of mock
79# srpmAutoBuild_mock-chroot '/build-secondary.sh' [&] # runs /build-secondary.sh in mock non-interactively from a shell OUTSIDE of mock
80#
81#
82# ---------------------------------------------- CLEAN - CLEANUP MOCK AND INSTALL BUILD RPMS----------------------------------------------
83#
84# dnf localinstall ${RPM_BUILD_DIR}/RPMS/*.rpm # optional - install packages. This will get ALL packages that were built, including debuginfo/debugsoure packages, so you may want to be more selective
85# mock-clean # transfer built RPMs (and SRPMs sources) into ${LOCALREPO_DIR} and cleanup mock
86# localrepo_updateDatabase # optional, if using ${LOCALREPO_DIR} as an actual dnf repository this will update it with the newly built packages
87# dnf upgrade --disablerepo=[a-z]* --enablerepo=localrepo-built # install upgrade using only the [newly/previously] built packages. This is probably better then using dnf localinstall in most cases
88#
89#
90# ---------------------------------------------- MISC NOTES ----------------------------------------------
91#
92# Notes regarding `srpmAutoBuild_mock-chroot[0]`:
93# running `srpmAutoBuild_mock-chroot[0]` without any function inputs gives you an interactive chroot shell inside of mock
94# running `srpmAutoBuild_mock-chroot[0]` with function inputs will run the input(s) as commands (non-interactively, using chroot) inside of mock
95# `srpmAutoBuild_mock-chroot` and `srpmAutoBuild_mock-chroot0` do the same thing, except `srpmAutoBuild_mock-chroot` automatically mounts/binds ${LOCALREPO_DIR} into mock before the command is run and and then unmounts ${LOCALREPO_DIR} in mock after the command has finished
96# `srpmAutoBuild_mock-chroot` and `srpmAutoBuild_mock-chroot0` both automatically source the srpmAutoBuild functions and setup environment variables
97#
98# run `srpmAutoBuild_checkBuildStatus` (from another non-SRPM-building terminal) to check the current build progress and build stats
99#
100# run `srpmAutoBuild_help [functionName]` to see help text for (most) srpmAutoBuild functions. Globs are accepted.
101#
102# Recommendation: customize the FLAGS in srpmAutoBuild_setEnvVars based on your hardware before using these functions for building anything.
103#
104# NOTE: IT IS NOT RECOMMENDED TO USE THESE CODES IF ANY OF THE SPEC / SRPM FILES CONTAIN SPACE CHARACTERS ANYWHERE IN THEIR PATH. It *should* still work, but A LOT of the code assumes everything is space-separated so this is asking for trouble.
105#
106# Note: if you see a build error related to major/minor/makedev on some c source file, you can fix it using `srpmAutoBuild_fixSpecFile_majorMinorMakedevError <specFilePath> <c-source code file path>`. This fix isnt automatically implemented, but running that command and then re-running `srpmAutoBuild_build <specFilePath>` on the file will (probably) build it correctly.
107#
108# NOTE: to make using these easier, run `srpmAutoBuild_makeAliases`. This will alias the functions and change the leading "srpmAutoBuild_" to "sab_" and the leading "localrepo_" to "lr_" (can also use user defined replacements)
109#
110# One item missing from these functions is automated gpg signing of the built RPM packages. Its on the to-do list, just havent gotten around to it yet.
111
112
113# # # # # # # # # # # # # # # # # # # # # # START OF FUNCTIONS # # # # # # # # # # # # # # # # # # # # # #
114
115# # # # # # # # # # # # # # # # MAIN FUNCTION FOR FULLY AUTOMATED UPDATING # # # # # # # # # # # # # # # #
116
117alias srpmAutoBuild_myALL='srpmAutoBuild_ALL -p -nc -sf -iu'
118
119srpmAutoBuild_ALL() {
120 # This function will run the entire process automated, starting with initializing the mock environment and ending with cleaning up the mock environment after all packages have been built.
121 #
122 # -------------------------- FLAGS --------------------------
123 #
124 # use flag '-ni' or '--no-init' to re-use the existing mock environment. The relevant script files will still be re-copied into mock, in case they are missing or have been modified/updated. If the mock root dir is empty then mock-init will still be called
125 #
126 # use flag '-nc' or '--no-clean' to skip running srpmAutoBuild_mock-clean after building and leave the mock environment intact
127 #
128 # use flag '-nd' or '--no-down' or '--no-download' to skip running srpmAutoBuild_mock-downloadSRPMs
129 # use flag '-da' or '--down-all' or '--download-all' to force downloading of ALL SRPMS of unbuilt and potentially upgradeable packages. srpmAutoBuild will try to avoid downloading srpms if it knows it cant build them
130 #
131 # use flag '-f' or '--force' to pass the --force flag to srpmAutoBuild_build. This causes it to build SRPMS (if it can) even if it thinks they have already been built.
132 # use flag '-na' or '--no-auto-match' to Flag to srpmAutoBuild_build to only accept exact filename matches. By default it tries to match files that are close (and likely what was intended) but not quite an exact match.
133 #
134 # use flag '-i0' or '-in' or '--no-install' to automatically not install them. Default behavior is to ask, and then if no response to not install anything.
135 # use flag '-i' or '--install' to use the default install flag hard-coded into the function
136 # use flag '-i1' or '-iu' or '--install-update' to automatically add packages to the local repo and then run `dnf update` with only 'localrepo-built' enabled./ Implies '+r' and requires that 'localrepo' (specifically, localrepo-built') is already setup as an actual dnf repository (manually run `localrepo_setupDNF` to set this up, if needed)
137 # use flag '-i2' or '-is' or '--install-standard[-only]' to automatically install packages after they are done building. This will install the main rpms, but not the debug rpms
138 # use flag '-i3' or '-id' --install-debug[-only]' to automatically install all the debug packages but none of the standard rpms packages after they are done building.
139 # use flag '-i4' or '-ia' or '--install-all' to automatically install all packages after they are done building. This includes the debug rpms
140 # add '+r' to end of install flag (e.g., -is+r') to also update the local repo with newly built packages
141 #
142 # use flag '-p' or '--parallel' to force using a 2nd build run
143 # use flag '-np' or '--no-parallel' to force using only 1 build run
144 # Note: default is to ask for user response with timeout, then (if no response) use 2 threads for systems with 8+ cores and 16+ gigs of ram and 'konsole' installed. Note: This is setup assuming you are using / have installed 'konsole'. It will need to be modified for other terminals.
145 #
146 # NOTE: any other inputs will be passed to srpmAutoBuild_build
147 #
148 # NOTE: FLAGS are NOT case sensitive. Actual flags accepted are slightly more general than described above. e.g., most allow for any number of leading dashes (so long as there is at least 1), and dont require the inter-word dashes. See the regex-based filters used to ID flags in the code for more info.
149 #
150 # Side note: personally, I often use something like `srpmAutoBuild_ALL -sf -p -i+r -nc`
151
152 local useParallelBuild=""
153 local parallelBuildUserResponse=""
154 local isolateKernelBuildUserResponse=""
155 local newlyBuiltRpmList=""
156 local rpmBuildFLAGS=""
157 local noInitFlag=0
158 local noDownloadFlag=0
159 local noCleanFlag=0
160 local forceFlag=0
161 local noAutoMatchFlag=0
162 local updateRepoFlag=0
163 local flagMatchCur=0
164 local installFlag=""
165 local flagCheckFlag=0
166 local isolateKernelBuildFlag
167 local userInstallFlag
168 local inAll=("${@}")
169
170 # OPTIONAL - set default install flag
171 local defaultInstallFlag="1"
172
173 # setup RPM_BUILD_DIR and MOCK_ROOT_DIR
174 srpmAutoBuild_rootUserCheck
175 srpmAutoBuild_mockSetupCheck
176 srpmAutoBuild_setRpmBuildDir -c
177 srpmAutoBuild_setEnvVars
178
179 echo -e "Beginning initial setup. This includes (unless disabled via flags): \n----> cleaning up an existing mock, if it exists \n----> (re)initializing mock \n----> setting up mock (e.g., copying files into mock and making build run scripts) \n----> downloading source SRPMs to build inside of the mock chroot environment"
180
181 # extract FLAGS
182
183 echo -e "\n\n${#inAll[@]} Inputs detected. Checking inputs for flags... \n"
184
185 #[[ "${inAll[*]}" =~ ^(.+ )?-+i([0-4]|((nstall)?(-?((u(pdate)?)|(a(ll)?)|(s(tandard(-?only)?))|(d(ebug(-?only)?))))?)?)( .+)? ]] || [[ -z "${defaultInstallFlag}" ]] && inAll[${#inAll[@]}]="-i${defaultInstallFlag#*-i}"
186
187 #while (( $# > 0 )); do
188 for nn in {"${inAll[@]}",''}; do
189
190 [[ -z "${nn}" ]] && [[ -z "${installFlag}" ]] && [[ -n "${defaultInstallFlag}" ]] && nn='-i' && flagMatchCur=9 || [[ -z "${nn}" ]] && flagMatchCur=8 || flagMatchCur=0
191
192 [[ -n "${nn}" ]] && echo "Checking input ${nn}"
193
194 # run init function, unless --no-init Flag set, then run copyFilesIntoMock function
195 (( $flagMatchCur == 0 )) && [[ ${nn,,// /} =~ ^-+no?-?i(nit)?$ ]] && flagMatchCur=1 && echo "'noInit' flag enabled - mock will not be scrubbed+cleaned+reinitialized if it already exists" && ((noInitFlag++))
196
197 # download unbuilt / upgradeable srpms unless --no-download Flag given
198 (( $flagMatchCur == 0 )) && [[ ${nn,,// /} =~ ^-+no?-?d(own(load)?)?$ ]] && flagMatchCur=1 && echo "'noDownload' flag enabled - new SRPMs will not automatically be downloaded" && ((noDownloadFlag++))
199
200 # clean mock chroot after building, unless --no-clean Flag set, then leave it as it is
201 (( $flagMatchCur == 0 )) && [[ ${nn,,// /} =~ ^-+no?-?c(lean)?$ ]] && flagMatchCur=1 && echo "'noClean' flag enabled - the mock environment will be left as-is when building is completed" && ((noCleanFlag++))
202
203 # dont re-build already-built RPMS unless --force Flag is set (flag is for srppmAutpBuild_build)
204 (( $flagMatchCur == 0 )) && [[ ${nn,,// /} =~ ^-+f(orce)?$ ]] && flagMatchCur=1 && echo "'force' flag enabled - the '--force' flag will be passed to 'srpmAutoBuild_build' to force re-building already-built RPMs" && ((forceFlag++))
205
206 # try to find matching SRPMs / SPECs for incomplete filename inputs unless '--no-auto-match' Flag is set (flag is for srppmAutpBuild_build)
207 (( $flagMatchCur == 0 )) && [[ ${nn,,// /} =~ ^-+n(a|o?-?auto(-?match)?)$ ]] && flagMatchCur=1 && echo "'noAuto' flag enabled - the '--no-auto-match' flag will be passed to 'srpmAutoBuild_build' to prevent it from trying to match inputs that are not valid file paths to SRPMs/SPECs present on the system" && ((noAutoMatchFlag++))
208
209 # flag to install packages that were just built (or not install them). Default behavior is to ask, then if no response to not install
210 ( ( (( $flagMatchCur == 0 )) && [[ ${nn,,// /} =~ ^-+i(nstall)?(\+r)?$ ]] ) || ( (( $flagMatchCur == 9 )) && ( [[ ${nn,,// /} =~ ^-+i(nstall)?(\+r)?$ ]] || [[ -z "${nn}" ]] ) ) ) && [[ -n "${defaultInstallFlag}" ]] && nn="-i${defaultInstallFlag#*-i}$([[ ${nn} == *'+r' ]] && [[ ! "${defaultInstallFlag}" == *'+r' ]] && echo -n '+r' || echo -n '')" && echo "Input '-i' re-evaluated to '${nn}'"
211 ( (( $flagMatchCur == 0 )) || (( $flagMatchCur == 9 )) ) && [[ ${nn,,// /} =~ ^-+i(0|((nstall)?-?n(one)?))$ ]] && installFlag=0 && flagMatchCur=$((( $flagMatchCur + 2 ))) && echo "'install' flag set to level 0 - built RPM packages wont be installed"
212 ( (( $flagMatchCur == 0 )) || (( $flagMatchCur == 9 )) ) && [[ ${nn,,// /} =~ ^-+i(1|((nstall)?-?u(pdate)?))(\+r)?$ ]] && installFlag=1 && updateRepoFlag=1 && flagMatchCur=$((( $flagMatchCur + 2 ))) && echo "'install' flag set to level 1 - built packages will be added to the local repo, and 'dnf upgrade' will be run with only 'localrepo-built' enabled (this automatically sets the '+r' update repository flag)"
213 ( (( $flagMatchCur == 0 )) || (( $flagMatchCur == 9 )) ) && [[ ${nn,,// /} =~ ^-+i(2|((nstall)?-?s(tandard(-?only)?)?))(\+r)?$ ]] && installFlag=2 && flagMatchCur=$((( $flagMatchCur + 2 ))) && echo "'install' flag set to level 2 - all newly built standard RPM packages will be installed, but built debuginfo RPM packages wont be installed"
214 ( (( $flagMatchCur == 0 )) || (( $flagMatchCur == 9 )) ) && [[ ${nn,,// /} =~ ^-+i(3|((nstall)?-?d(ebug(-?only)?)?))(\+r)?$ ]] && installFlag=3 && flagMatchCur=$((( $flagMatchCur + 2 ))) && echo "'install' flag set to level 3 - all newly built debuginfo RPM packages will be installed, but built standard RPM packages wont be installed"
215 ( (( $flagMatchCur == 0 )) || (( $flagMatchCur == 9 )) ) && [[ ${nn,,// /} =~ ^-+i(4|((nstall)?-?a(ll)?))(\+r)?$ ]] && installFlag=4 && flagMatchCur=$((( $flagMatchCur + 2 ))) && echo "'install' flag set to level 4 - all newly built RPM packages (standard + debuginfo) will be installed"
216 ( (( $flagMatchCur == 2 )) || (( $flagMatchCur == 11 )) ) && [[ ${nn,,// /} =~ ^-+i.*\+r$ ]] && updateRepoFlag=1 && echo "'updateRepo' flag enabled - in addition to [some|all] packages being installed, the local repository 'localrepo' will be automatically updated as well"
217 (( $flagMatchCur == 2 )) && flagMatchCur=1
218
219 # flag to force 1 or 2 build processes
220 (( $flagMatchCur == 0 )) && [[ ${nn,,// /} =~ ^-+p(arallel)?$ ]] && parallelBuildUserResponse=yes && flagMatchCur=1 && echo "'parallelBuild' flag enabled - a 2nd parallel build run will automatically be launched at the appropriate time to build SRPMs faster"
221 (( $flagMatchCur == 0 )) && [[ ${nn,,// /} =~ ^-+no?-?p(arallel)?$ ]] && parallelBuildUserResponse=no && flagMatchCur=1 && echo "'parallelBuild' flag disabled - only a single build run will be used to build SRPMs"
222
223 # flag to ask for confirmation of flags before continuing
224 (( $flagMatchCur == 0 )) && [[ ${nn,,// /} =~ ^-+((s(how)?)|(c(check)?))-?f(lags)?$ ]] && flagCheckFlag=1 && flagMatchCur=1 && echo "'flagCheck' flag enabled - flags will be displayed and you will be prompted for confirmation prior to running this functions main contents"
225
226 # If no matching FLAGS then add it to $rpmBuildFLAGS --> it will be passed to srpmAutoBuild_build
227 (( $flagMatchCur == 0 )) && rpmBuildFLAGS="$(echo "${rpmBuildFLAGS}" "${1}")" && echo "${1} was not recognized as as explicitly defined flag...It will be passed to the setup functions called by this program for them to parse (if able)"
228
229 (( $flagMatchCur < 5 )) && shift 1
230 echo ""
231
232 done
233
234 # get FLAGS from srpmAutoBuild_build to pass to srpmAutoBuild_generateBuildScripts and setup string of full command
235
236 (( $forceFlag > 0 )) && rpmBuildFLAGS="--force ${rpmBuildFLAGS}"
237 (( $noAutoMatchFlag > 0 )) && rpmBuildFLAGS="--no-auto-match ${rpmBuildFLAGS} "
238 rpmBuildFLAGS="${rpmBuildFLAGS## }"
239 rpmBuildFLAGS="${rpmBuildFLAGS%% }"
240
241 if (( $flagCheckFlag > 0 )); then
242 # list flags
243 echo -e "\nThe following flags have been set: \n"
244 echo -e "\trpmBuildFLAGS = ${rpmBuildFLAGS}"
245 echo -e "\tnoInitFlag = ${noInitFlag}"
246 echo -e "\tnoDownloadFlag = ${noDownloadFlag}"
247 echo -e "\tnoCleanFlag = ${noCleanFlag}"
248 echo -e "\tupdateRepoFlag = ${updateRepoFlag}"
249 echo -e "\tinstallFlag = ${installFlag}"
250 echo -e "\tuseParallelBuildRuns = ${parallelBuildUserResponse}"
251 echo -e "\n\nDo these look correct? A response of '' (<NULL>), 'y', or 'yes' will continue the program. Any other non-null response will exit the program. Timeout is 20 seconds."
252
253 local tempVar=""
254 read -e -p "Response: " -t 20 tempVar
255
256 [[ -n "${tempVar}" ]] && [[ ! ${tempVar,,} =~ ^y(es)?$ ]] && exit
257 fi
258
259 #if (( $noInitFlag > 0 )); then
260 # srpmAutoBuild_copyFilesIntoMock
261 # srpmAutoBuild_generateBuildScripts "${rpmBuildFLAGS}"
262 #else
263 # [[ -n "${rpmBuildFLAGS}" ]] && srpmAutoBuild_mock-init "${rpmBuildFLAGS}" || srpmAutoBuild_mock-init
264 #fi
265
266 srpmAutoBuild_mock-init $(echo "$( (( $noInitFlag > 0 )) && echo '--no-clean' || echo "") ${rpmBuildFLAGS}" | sed -E s/' +'/' '/g | sed -E s/'^ $'//)
267
268 # download not-yet-built SRPMs into the Mock
269 (( $noDownloadFlag == 0 )) && srpmAutoBuild_mock-downloadSRPMs --enable-repos
270
271 # bind '${LOCALREPO_DIR}' into the mock environment
272 srpmAutoBuild_mock-bind-localrepo
273
274 # setup dnf cache in mock
275 echo -e "\nThe code will now attempt to generate the dnf cache in the mock environment... \nNote: you will not see the typical DNF text output during this command. \n"
276 srpmAutoBuild_mock-makecache
277
278 # call setup and build commands in a non-interactive chroot shell
279 # If the machine has 8+ cores and 16+ gigs of memory, default is to run 2 build processes at once.
280
281 if [[ -n "${parallelBuildUserResponse}" ]] && [[ ! ${parallelBuildUserResponse,,} =~ ^((y(es)?)|(no?))$ ]]; then
282 # get user response for whether to use 2 parallel build runs
283
284 (( $(nproc) >= 8 )) && (( $(srpmAutoBuild_getTotalMem) >= ( 2 ** 24 ) )) && [[ -n $(rpm -qa | grep -E '^konsole') ]] && useParallelBuild=YES || useParallelBuild=NO
285
286 echo -e "\n\nWould you like to use 2 parallel build processes?? \n\nThe default based on CPU and memory and software availability is: ${useParallelBuild} \n\nWARNING: Spawning the parallel build run uses 'konsole'. If konsole is not installed and parallel builds are enabled then both build runs will fail. \n\nNote: Timeout is 20 seconds. After 20 seconds the default option will be chosen automatically. \n"
287
288 read -ie -p "Enter y[es] or n[o]: " -t 20 parallelBuildUserResponse
289 fi
290
291 [[ ${parallelBuildUserResponse,,} =~ ^(y(es)?|no?)$ ]] && useParallelBuild="${parallelBuildUserResponse,,}"
292
293 if [[ -n "$(find "${RPM_BUILD_DIR}/SRPMS" -maxdepth 1 -type f -regex "^.*\/kernel-[0-9]+\.[0-9]+\.[0-9]+-[0-9]+\.[^\.]+\.src\.rpm$")" ]]; then
294 # new kernel SRPM detected
295
296 echo -e "\nNOTICE: a new kernel SRPM has been detected! \nWould you like to isolate building this kernel?\n\ny[es] --> (DEFAULT) Build the kernel in a newly initiated mock chroot after everything else has finished building. Selecting 'yes' will spawn a 2nd prompt asking you if youd like to install it. \n\nn[o] ---> treat the new kernel like all the other SRPM packages. It will be built with and use the same install options as all the other SRPMS. \n\nNote: Timeout is 20 seconds. After 20 seconds the default option will be chosen automatically. \n"
297
298 read -ie -p "Enter y[es] or n[o]: " -t 20 isolateKernelBuildUserResponse
299
300 [[ ${isolateKernelBuildUserResponse,,} =~ ^no?$ ]] && isolateKernelBuildFlag=0 || isolateKernelBuildFlag=1
301
302 if (( $isolateKernelBuildFlag == 1)) && (( $noCleanFlag == 1)); then
303
304 echo -e "\nWARNING: \nIsolating the kernel build requires cleaning the mock chroot, and the '--no-clean' flag is currently set. \nIsolating the kernel build will leave the final post-kernel-build chroot intact, but the initial chroot \n(where all the non-kernel packages were built) will be cleaned+scrubbed to prepare for the isolated kernel build.\n\nDo you still want to isolate the new kernel build? \n\ny[es] --> (DEFAULT) Isolate the new kernel build and clean the intermediate chroot before the isolated kernel build \n\nn[o] ---> enforce the '--no-clean' flag and dont isolate the new kernel build. This will treat the new kernel like all the other SRPM packages. It will be built with and use the same install options as all the other SRPMS. \n\nNote: Timeout is 20 seconds. After 20 seconds the default option will be chosen automatically. \n"
305
306 isolateKernelBuildUserResponse=""
307 read -ie -p "Enter y[es] or n[o]: " -t 20 isolateKernelBuildUserResponse
308
309 [[ ${isolateKernelBuildUserResponse,,} =~ ^no?$ ]] && isolateKernelBuildFlag=0 || isolateKernelBuildFlag=1
310 fi
311
312 if (( $isolateKernelBuildFlag == 1)); then
313
314 [[ -d ${LOCALREPO_DIR}/.MISC/kernel-temp ]] && chmod -R 777 ${LOCALREPO_DIR}/.MISC/kernel-temp || mkdir --parents ${LOCALREPO_DIR}/.MISC/kernel-temp
315 chmod 777 $(find "${RPM_BUILD_DIR}/SRPMS" -maxdepth 1 -type f -regex "^.*\/kernel-((headers-)|(tools-))?[0-9]+\.[0-9]+\.[0-9]+-[0-9]+\.[^\.]+\.src\.rpm$") && \mv -f $(find "${RPM_BUILD_DIR}/SRPMS" -maxdepth 1 -type f -regex "^.*\/kernel-((headers-)|(tools-))?[0-9]+\.[0-9]+\.[0-9]+-[0-9]+\.[^\.]+\.src\.rpm$") ${LOCALREPO_DIR}/.MISC/kernel-temp
316
317 echo -e "\nThe kernel build will be isolated.\n\nWould you also like to install the kernel, or just build the kernel RPMs? \n\ny[es] --> build the new kernel and install the standard rpm's for the new \n\nyes+debug --> build the new kernel and install the standard and debuginfo rpm's for the new kernel \n\nn[o] ---> (DEFAULT) build the new kernel but do not install the RPMs automatically \n\nNote: Timeout is 20 seconds. After 20 seconds the default option will be chosen automatically. \n"
318
319 isolateKernelBuildUserResponse=""
320 read -ie -p "Enter y[es] or yes+debug or n[o]: " -t 20 isolateKernelBuildUserResponse
321
322 [[ "${isolateKernelBuildUserResponse,,}" == "yes+debug" ]] && isolateKernelBuildFlag=3
323 [[ ${isolateKernelBuildUserResponse,,} =~ ^y(es)?$ ]] && isolateKernelBuildFlag=2
324
325 fi
326
327 else
328 # no new kernel SRPM was found
329
330 isolateKernelBuildFlag=0
331 fi
332
333 # clear on-disk build stat files
334 for nn in {BUILD_LIST_1,BUILT_LIST_2,STATUS_1,STATUS_2,STATS_OVERALL,SECONDARY_BUILD.lock}; do
335 [[ -f "${RPM_BUILD_DIR}/.${nn}" ]] && chmod 777 "${RPM_BUILD_DIR}/.${nn}" && \rm -f "${RPM_BUILD_DIR}/.${nn}"
336 done
337
338 if [[ ${useParallelBuild,,} =~ ^y(es)?$ ]]; then
339 # use 2 build processes
340
341 # launch secondary build run forked. It will automatically wait for the main build run before starting
342
343 XDG_RUNTIME_DIR="/tmp/runtime-${USER}" && export XDG_RUNTIME_DIR
344 [[ -d "${XDG_RUNTIME_DIR}" ]] || mkdir --parents "${XDG_RUNTIME_DIR}"
345 chmod 0700 "${XDG_RUNTIME_DIR}"
346
347 #chmod 777 "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" && \rm -f "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" && touch "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock"
348
349 # make sure we can access directories
350 chmod 777 "${RPM_BUILD_DIR}"
351 chmod 777 ${RPM_BUILD_DIR}/*
352 #[[ -f "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" ]] && chmod 777 "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" || touch "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" && chmod 777 "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock"
353
354 chmod 777 "${MOCK_ROOT_DIR}"
355 chmod 777 ${MOCK_ROOT_DIR}/*
356 chmod 777 ${MOCK_ROOT_DIR}/builddir/*
357
358 ( [[ -f "${MOCK_ROOT_DIR}/build-main.sh" ]] && [[ -f "${MOCK_ROOT_DIR}/build-secondary.sh" ]] ) || srpmAutoBuild_generateBuildScripts
359 chmod 777 "${MOCK_ROOT_DIR}/build-main.sh" "${MOCK_ROOT_DIR}/build-secondary.sh"
360
361 # launch forked processes for main and secondary builds
362
363 echo "NOW LAUNCHING FORKED BUILD RUN PROCESSES. 2 NEW KONSOLE TERMINALS SHOULD APPEAR."
364 sleep 2
365
366 #su -l -c "konsole --separate -e \"su -l -c \\\"source \\\\\\\"/usr/local/bin/my-scripts/srpmAutoBuild.sh\\\\\\\" && /bin/bash -c \\\\\\\"source /usr/local/bin/my-scripts/srpmAutoBuild.sh && ( while [[ \\\\\\\\\\\\\\\"x\$(srpmAutoBuild_mock-chroot0 \\\\\\\\\\\\\\\"echo\\\\\\\\\\\\\\\" 1>/dev/null 2>&1)\\\\\\\\\\\\\\\" != \\\\\\\\\\\\\\\"x\\\\\\\\\\\\\\\" ]]; do sleep 1; done ) && srpmAutoBuild_mock-chroot0 \\\\\\\\\\\\\\\"/build-main.sh\\\\\\\\\\\\\\\"\\\\\\\"\\\"\"" &
367
368 # run main build run in current session
369 #su -l -c "konsole --separate -e \"su -l -c \\\"source \\\\\\\"/usr/local/bin/my-scripts/srpmAutoBuild.sh\\\\\\\" && /bin/bash -c \\\\\\\"source /usr/local/bin/my-scripts/srpmAutoBuild.sh && sleep 10 && ( while [[ \\\\\\\\\\\\\\\"x\$(srpmAutoBuild_mock-chroot0 \\\\\\\\\\\\\\\"echo\\\\\\\\\\\\\\\" 1>/dev/null 2>&1)\\\\\\\\\\\\\\\" != \\\\\\\\\\\\\\\"x\\\\\\\\\\\\\\\" ]]; do sleep 1; done ) && srpmAutoBuild_mock-chroot0 \\\\\\\\\\\\\\\"/build-secondary.sh\\\\\\\\\\\\\\\"\\\\\\\"\\\"\"" &
370
371 su -l -c "konsole --separate -e \"su -p --session-command \\\"source \\\\\\\"/usr/local/bin/my-scripts/srpmAutoBuild.sh\\\\\\\" && sleep 1 && ( while [[ \\\\\\\"x\$(srpmAutoBuild_mock-chroot0 \\\\\\\"echo\\\\\\\" 1>/dev/null 2>&1)\\\\\\\" != \\\\\\\"x\\\\\\\" ]]; do sleep 1; done ) && srpmAutoBuild_mock-chroot0 \\\\\\\"/build-main.sh\\\\\\\"\\\"\"" &
372
373 # run main build run in current session
374 su -l -c "konsole --separate -e \"su -p --session-command \\\"source \\\\\\\"/usr/local/bin/my-scripts/srpmAutoBuild.sh\\\\\\\" && sleep 10 && ( while [[ \\\\\\\"x\$(srpmAutoBuild_mock-chroot0 \\\\\\\"echo\\\\\\\" 1>/dev/null 2>&1)\\\\\\\" != \\\\\\\"x\\\\\\\" ]]; do sleep 1; done ) && srpmAutoBuild_mock-chroot0 \\\\\\\"/build-secondary.sh\\\\\\\"\\\"\"" &
375
376 #srpmAutoBuild_mock-chroot0 '/build-main.sh' &
377 #srpmAutoBuild_mock-chroot0 '/build-main.sh' &
378
379 # wait for everything to finish
380 wait
381
382 else
383 # use 1 build process
384 [[ -f "${MOCK_ROOT_DIR}/build-main.sh" ]] || srpmAutoBuild_generateBuildScripts
385 chmod 777 "${MOCK_ROOT_DIR}/build-main.sh"
386
387 srpmAutoBuild_mock-chroot0 '/build-main.sh'
388
389 fi
390
391 # install packages. Ask for user response on if / which rpms to install if this wasnt given as a function input
392
393 [[ -z ${installFlag} ]] && echo -e "\n\nWould you like to install the RPM';'s that just finished building? \n(you have 10 seconds to make a selection - enter a number between 0-3)\n\n0: (DEFAULT) dont install anything \n1: (DEFAULT w/ active localrepo) update localrepo-built with the built RPMs using 'loicalrewpo_updateDatabase' and update packages using 'dnf update' with only the localrepo-built repo enabled \n2: install all standard rpms, but not debug rpms \n3: install all debug rpms, but not standard rpms \n4: install ALL rpms\n\nIf installing, add 0 to the response (making it one of {10,20,30,40}) to also update the local repo with the installed packages using \"localrepo_updateDatabase \n\nNote for response '1': updating the local repo is implied, but response '10' is also accepted. If localrepo[-built] doesnt exist, it will be created automatically.)\" \n\nNote: Timeout is 20 seconds. After 20 seconds the default option will be chosen automatically. \n" && read -ie -p "Your selection: " -t 20 userInstallFlag
394
395 [[ ${userInstallFlag} =~ ^[0-4]$ ]] && installFlag=${userInstallFlag}
396 [[ ${userInstallFlag} =~ ^((10)|(20)|(30)|(40))$ ]] && installFlag=$((( $userInstallFlag / 10 ))) && updateRepoFlag=1
397
398 (( $installFlag == 1 )) && updateRepoFlag=1 && ( [[ -z "$(dnf repolist | grep 'localrepo-built')" ]] && localrepo_setupDNF )
399
400 if [[ -z ${installFlag} ]]; then
401 [[ -z "$(dnf repolist | grep 'localrepo-built')" ]] && installFlag=0 || installFlag=1
402 fi
403
404 # update localrepo if requested. This will copy packages, not move them, so they will still be in mock
405 (( $updateRepoFlag > 0 )) && localrepo_updateDatabase
406
407 if (( $installFlag > 1 )); then
408
409 newlyBuiltRpmList=""
410 newlyBuiltRpmList="$(find ${RPM_BUILD_DIR}/RPMS -type f -name "*.rpm")"
411
412 (( $installFlag == 2 )) && newlyBuiltRpmList="$(echo "${newlyBuiltRpmList}" | grep -v -E 'debug(info|source)')"
413 (( $installFlag == 3 )) && newlyBuiltRpmList="$(echo "${newlyBuiltRpmList}" | grep -E 'debug(info|source)')"
414
415 [[ -n "${newlyBuiltRpmList}" ]] && dnf -y localinstall ${newlyBuiltRpmList}
416
417 elif (( $installFlag == 1 )); then
418
419 dnf -y reinstall $(srpmAutoBuild_listDownloadRPMs ${RPM_BUILD_DIR}/RPMS)
420 dnf -y upgrade $(srpmAutoBuild_listDownloadRPMs ${RPM_BUILD_DIR}/RPMS)
421
422 localrepo_dnf --built --allowerasing -y upgrade
423
424 #dnf --refresh --skip-broken --allowerasing --disablerepo=[a-zA-Z0-9]* --enablerepo=localrepo-built -y update
425
426 fi
427
428 # build the new kernel now, if there is a new one and the user selected to isolate the build
429 if (( $isolateKernelBuildFlag > 0 )); then
430
431 srpmAutoBuild_mock-clean
432 srpmAutoBuild_mock-init
433 srpmAutoBuild_mock-bind-localrepo
434
435 \mv -f ${LOCALREPO_DIR}/.MISC/kernel-temp/*.src.rpm "${RPM_BUILD_DIR}/SRPMS"
436
437 srpmAutoBuild_mock-chroot0 '/build-main.sh'
438
439 if (( $isolateKernelBuildFlag > 1 )); then
440
441 newlyBuiltRpmList="$(find ${RPM_BUILD_DIR}/RPMS -type f -name "kernel{-,-headers-,-tools-}*.rpm")"
442
443 (( $isolateKernelBuildFlag == 2 )) && newlyBuiltRpmList="$(echo "${newlyBuiltRpmList}" | grep -v -E 'debug(info|source)')"
444 (( $isolateKernelBuildFlag == 3 )) && newlyBuiltRpmList="$(echo "${newlyBuiltRpmList}" | grep -E 'debug(info|source)')"
445
446 [[ -n "${newlyBuiltRpmList}" ]] && dnf -y localinstall ${newlyBuiltRpmList}
447
448 fi
449
450 fi
451
452 # cleanup mock environment, unless --no-clean Flag set
453 (( $noCleanFlag == 0 )) && srpmAutoBuild_mock-clean
454
455 # note: mock-clean will automatically un-mount '${LOCALREPO_DIR}' and transfer out all the built RPMs (as well as the SRPMs and the spec-files) to directories in '${LOCALREPO_DIR}' before running the actual cleaning function.
456}
457
458
459srpmAutoBuild_mock-config-setup() {
460 # modifies the original config file in /etc/mock so that it works better by default with srpmAutoBuild
461 # default behavior is to re-save the original config file as '/etc/mock/$(srpmAutoBuild_getMockName).cfg.orig'; and to only regenerate the config file if that file doesnt exist.
462 #
463 # # # # # FLAGS # # # # #
464 #
465 # use flag '-f' or '--force' to force regeneration even if the *.orig config file exists. in this case the current config is saves as '*.orig[#]', where '[#]' is the lowest number that creates a unique filename
466 #
467 # use flag '-f_[#]' or '--force_[#]' to use the backup config file '/etc/mock/$(srpmAutoBuild_getMockName).cfg.orig[#]' as the source config file that is modified
468 # # '-f_' --> use '/etc/mock/$(srpmAutoBuild_getMockName).cfg.orig'
469 # # '-f_0' --> use '/etc/mock/$(srpmAutoBuild_getMockName).cfg.orig0'
470 # # '-f_9999' --> use '/etc/mock/$(srpmAutoBuild_getMockName).cfg.orig9999'
471 #
472
473 # get mock config file path
474 local mockConfigCur=""
475 mockConfigCur="/etc/mock/$(srpmAutoBuild_getMockName).cfg"
476
477 # check original config file exists, otherwise exis with status 1
478 [[ ! ${1,,} =~ ^-+f(orce)?_[0-9]*$ ]] && [[ ! -f "${mockConfigCur}" ]] && echo -e "\nWARNING: original config file '${mockConfigCur}' not found, and thus cant be modified! \nExiting with status '1' \n" >&2 && return 1
479
480 # exit with status 0 if *.orig config file also exists and '--force' flag is not set
481 [[ -f "${mockConfigCur}.orig" ]] && [[ ! ${1,,} =~ ^-+f(orce)?(_[0-9]*)?$ ]] && echo -e "\nNOTICE: '${mockConfigCur}.orig' config file backup already exists. \n'${mockConfigCur}' config file will not be re-writen. \nTo force re-generating the config file, use flag '-f' or '--force'. \n" && return
482
483 # determine which config file to use as a source
484 local mockConfigSource=""
485 [[ ${1,,} =~ ^-+f(orce)?_[0-9]*$ ]] && mockConfigSource="${mockConfigCur}.orig$(echo "${1}" | sed -E s/'^-+[a-zA-Z]*_([0-9]*)$'/'\1'/)" || mockConfigSource="${mockConfigCur}"
486 [[ ! -f "${mockConfigSource}" ]] && echo -e "\nWARNING: The selected mock config source file '${mockConfigSource}' does not exist and thus cant be used as the configuration source. \nExiting with status '2' \n" >&2 && return 2 || echo "Using '${mockConfigSource}' as the source mock configuration file"
487
488 # get name for config backup path
489 local mockConfigBackup=""
490 mockConfigBackup="$(srpmAutoBuild_getUniqueName "${mockConfigCur}.orig")"
491
492 # move orig config to backup path
493 [[ -f "${mockConfigCur}" ]] && echo "Moving '${mockConfigCur}' to '${mockConfigBackup}' ..." >&2 && mv "${mockConfigCur}" "${mockConfigBackup}" && [[ ! ${1,,} =~ ^-+f(orce)?_[0-9]*$ ]] && mockConfigSource="${mockConfigBackup}"
494
495 # modify original config file and resave it as current mock config file
496 echo "Writing new config file to '${mockConfigCur}' ..." >&2
497 echo "$(echo -n "$(cat "${mockConfigSource}" | sed -zE s/'^(.*)\n\# *[Rr]epos.*$'/'\1'/ | sed -E s/'yum'/'dnf'/g | sed -E s/'dnf\.repos\.d'/'yum\.repos\.d'/ | sed -E s/'\('"'"'x86_64'"'"'\,?\)'/'\('"'"'x86_64'"'"','"'"'noarch'"'"'\)'/ | grep -v -E '^(fastestmirror|reposdir|cachedir|timeout|gpg_check|repo_gpgcheck|syslog_ident|install_weak_deps|metadata_expire|config_opts\['"'"'chroot_setup_cmd'"'"'\])'; echo -e "fastestmirror=1\nreposdir=/etc/yum.repos.d/\ncachedir=/var/cache/dnf/\ntimeout=20\ngpgcheck=0\nrepo_gpgcheck=0\nsyslog_ident=root\ninstall_weak_deps=1\nmetadata_expire=1h\n")" | sed -zE s/'^(.*[^\n])\n?(\nconfig_opts\['"'"'dnf\.conf'"'"'\] *=.*)$'/'\1\nconfig_opts\['"'"'copy-in'"'"'\] = \[ '"'"'\/etc\/yum\/repos.d'"'"' \]\nconfig_opts\['"'"'chroot_setup_cmd'"'"'\] = '"'"'install @development-tools @rpm-development-tools @c-development @buildsys-build vim ShellCheck kernel-devel kernel-modules kernel-modules-extra kernel-headers kernel-cross-headers kernel-rpm-macros kernel-core dnf dnf-plugins-core python3-dnf dnf-yum'"'"'\n\2'/)" > "${mockConfigCur}"
498
499 # add repo info to config file
500 echo "Adding repo info to config file '${mockConfigCur}' ..." >&2
501 if [[ -z "$(find "/etc/yum.repos.d" -type f)" ]]; then
502 echo "$(cat "${mockConfigBackup}" | sed -zE s/'^.*(\n\# *[Rr]epos.*)$'/'\1'/)" >> "${mockConfigCur}"
503 else
504 local nn=""
505
506 echo -e "\n# repos" >> "${mockConfigCur}"
507 for nn in /etc/yum.repos.d/*; do
508 echo -e "\n# repos from ${nn##*/} \n" >> "${mockConfigCur}"
509 echo "$(cat "${nn}")" >> "${mockConfigCur}"
510 done
511 echo -e "\n\"\"\"" >> "${mockConfigCur}"
512 fi
513
514 echo -e "\nNew config file has been generated and saved to '${mockConfigCur}' \n" >&2
515
516}
517
518
519srpmAutoBuild_mockSetupCheck() {
520 # checks the following:
521 # # that "/etc/mock/$(srpmAutoBuild_getMockName).cfg" exists, else[re]installs mock using dnf
522 # # checks that "/etc/mock/$(srpmAutoBuild_getMockName).cfg.orig" exists, else runs srpmAutoBuild_mock-config-setup
523
524 [[ ! -f "/etc/mock/$(srpmAutoBuild_getMockName).cfg" ]] && [[ -z "rpm -qa | grep -E '^mock-[^a-zA-Z]*\.fc[0-9]+\.noarch'" ]] && dnf install -y mock
525 [[ ! -f "/etc/mock/$(srpmAutoBuild_getMockName).cfg" ]] && dnf reinstall -y mock
526 [[ ! -f "/etc/mock/$(srpmAutoBuild_getMockName).cfg.orig" ]] && srpmAutoBuild_mock-config-setup
527
528}
529
530
531srpmAutoBuild_mock-zfs-build() {
532 # re-downloads and re-builds a new zfs module inside of mock
533
534 srpmAutoBuild_mock-clean
535 srpmAutoBuild_mock-init
536 srpmAutoBuild_mock-makecache
537 srpmAutoBuild_mock-chroot 'dnf install @development-tools autoconf automake libtool wget libtirpc-devel rpm-build zlib-devel libuuid-devel libattr-devel libblkid-devel libselinux-devel libudev-devel libaio-devel parted lsscsi ksh openssl-devel elfutils-libelf-devel kernel-devel-$(uname -r) lcov git sudo python3 python3-devel; srpmAutoBuild_setEnvVars; cd /builddir/build/BUILD; git clone https://github.com/zfsonlinux/zfs.git; cd /builddir/build/BUILD/zfs; srpmAutoBuild_setEnvVars && /builddir/build/BUILD/zfs/autogen.sh; /builddir/build/BUILD/zfs/configure -with-config=all --with-aix-soname=both --enable-debug --enable-debuginfo --enable-pyzfs --enable-systemd --enable-sysvinit -enable-code-coverage --enable-dependency-tracking --enable-shared --enable-static --enable-debug-kmem --enable-debug-kmem-tracking --with-python=3; make -k -j$(nproc); make -k -j1 pkg-utils srpm-utils srpm-common srpm-dkms srpm; zfsSrcRpms="$(find "/builddir/build/BUILD/zfs/" -type f -name "*.src.rpm")"; cp -a /builddir/build/BUILD/zfs/*.src.rpm /builddir/build/SRPMS && cd /builddir/build && srpmAutoBuild_build /builddir/build/zfs*.src.rpm'
538
539}
540
541
542# # # # # # # # # # # CODES TO MOUNT/BIND AND UNMOUNT A LOCAL PACKAGE REPO INTO MOCK # # # # # # # # # # #
543
544
545srpmAutoBuild_localrepoIsMounted() {
546 # Returns as "true" if ${MOCK_ROOT_DIR}${LOCALREPO_DIR} is a mount point (presumably bound to ${LOCALREPO_DIR})
547 # Returns as "false" if ${MOCK_ROOT_DIR}${LOCALREPO_DIR} is NOT currently a mount point
548
549 [[ -d "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR#/}" ]] && srpmAutoBuild_isMountPoint "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR#/}" && return 0 || return 1
550}
551
552
553srpmAutoBuild_isMountPoint() {
554 # Returns as "true" if input ( "${*}" ) IS a mount point
555 # Returns as "false" if input ( "${*}" ) IS NOT a mount point
556
557 [[ -z "$(mountpoint "${*}" | grep 'not')" ]] && return 0 || return 1
558
559}
560
561
562srpmAutoBuild_isNotEmpty() {
563 # checks if the directory/file is not empty (i.e., it either doesnt exist or exists but has no content)
564
565 [[ ! -e "${*}" ]] && return 1
566 [[ -d "${*}" ]] && [[ -z "$(find "${*}" -maxdepth 1 | grep -v -F "${*}")" ]] && return 1
567 [[ -f "${*}" ]] && [[ -z "$(cat "${*}")" ]] && return 1
568 return 0
569
570
571}
572
573
574srpmAutoBuild_mock-bind-localrepo() {
575 # mount/bind ${LOCALREPO_DIR} into mock environment
576 srpmAutoBuild_setEnvVars
577
578 if ! srpmAutoBuild_localrepoIsMounted; then
579
580 [[ -d "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR#/}" ]] || mkdir --parents "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR#/}"
581
582 [[ -d "${LOCALREPO_DIR}" ]] && ( srpmAutoBuild_isNotEmpty || ( [[ -d "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR#/}" ]] || mkdir "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR#/}" ) && mount -o bind,ro "${LOCALREPO_DIR}" "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR#/}" )
583
584 fi
585}
586
587
588srpmAutoBuild_mock-umount-localrepo() {
589 # sinple (non-forceful) umount of ${LOCALREPO_DIR} from mock
590 srpmAutoBuild_rootUserCheck
591
592 srpmAutoBuild_localrepoIsMounted && umount "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR#/}"
593}
594
595
596srpmAutoBuild_mock-force-umount-localrepo() {
597 # forceful umount of ${LOCALREPO_DIR} from mock.
598 # This should be run before cleaning mock (it is called automatically by srpmAutoBuild_mock-clean) to ensure that cleaning does not begin while ${LOCALREPO_DIR} is still mounted/bound in the mock environment, as this can lead to the entire ${LOCALREPO_DIR} being permanently deleted.
599 srpmAutoBuild_rootUserCheck
600
601 srpmAutoBuild_localrepoIsMounted && srpmAutoBuild_mock-umount-localrepo
602 srpmAutoBuild_localrepoIsMounted && umount -f "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR#/}"
603 srpmAutoBuild_localrepoIsMounted && srpmAutoBuild_mock-chroot0 'umount ${LOCALREPO_DIR}'
604 srpmAutoBuild_localrepoIsMounted && srpmAutoBuild_mock-chroot0 'umount -f ${LOCALREPO_DIR}'
605 srpmAutoBuild_localrepoIsMounted && echo -e "\n\nWARNING: The \"${LOCALREPO_DIR}\" bind/mount in the mock environment will not umount. \nCleaning the Mock environment with \"${LOCALREPO_DIR}\" bound / mounted, even in read-only mode, may lead to data loss. \n"
606
607 if srpmAutoBuild_localrepoIsMounted; then
608
609 [[ -d "/DATA/${LOCALREPO_DIR#/}" ]] && [[ -n $(find "/DATA/${LOCALREPO_DIR#/}") ]] && LOCALREPO_BACKUP_DIR="/DATA/${LOCALREPO_DIR#/}"
610
611 if [[ -n ${LOCALREPO_BACKUP_DIR} ]]; then
612 echo -e "\"${LOCALREPO_DIR}\" will be backed up to the pre-set backup directory at ${LOCALREPO_BACKUP_DIR}"
613 rsync -avP "${LOCALREPO_DIR%/}/" "${LOCALREPO_BACKUP_DIR%/}/"
614
615 else
616
617 echo -e "A backup directory has not been setup for \"${LOCALREPO_DIR}\". Please enter a backup location to backup the repo. \nNOTE: if you respond with the response\"NONE\", the repo will not be backed up. Only do this is you know what you are doing or dont care about any of the data in \"${LOCALREPO_DIR}\" \n\nIf you respond with an empty/null response, the default location of \"${LOCALREPO_DIR}-backup\" will be used."
618 read -ie -p "Backup Directory: " LOCALREPO_BACKUP_DIR
619
620 fi
621
622 ( [[ -z "${LOCALREPO_BACKUP_DIR}" ]] || [[ ${LOCALREPO_BACKUP_DIR} =~ ^\${LOCALREPO_DIR}(\/.*)?$ ]] ) && LOCALREPO_BACKUP_DIR="${LOCALREPO_DIR}-backup"
623
624 if [[ "${LOCALREPO_BACKUP_DIR}" != "NONE" ]]; then
625
626 LOCALREPO_BACKUP_DIR="${LOCALREPO_BACKUP_DIR%/}"
627 [[ -d "${LOCALREPO_BACKUP_DIR}" ]] || mkdir --parents "${LOCALREPO_BACKUP_DIR}"
628 export LOCALREPO_BACKUP_DIR
629
630 rsync -avP "${LOCALREPO_DIR%/}/" "${LOCALREPO_BACKUP_DIR%/}/"
631 fi
632
633 fi
634}
635
636# # # # # # # # # # # # # CODES TO RUN COMMANDS / GET AN INTERACTIVE SHELL IN MOCK # # # # # # # # # # # # #
637
638srpmAutoBuild_mock-chroot0() {
639 # enter the mock chroot (if no functions inputs) or run specified command non-interactively in mock. In either case, ~/.bashrc is sourced, which (if using the other srpmAutoBuild_mock-* functions) will setup everything needed to run srpmAutoBuild from within mock.
640
641 local inputCmds=""
642 local cmdType=""
643
644 #&& inputCmds='[[ -f "/usr/local/bin/my-scripts/srpmAutoBuild.sh" ]] && chmod 777 "/usr/local/bin/my-scripts/srpmAutoBuild.sh" && source "/usr/local/bin/my-scripts/srpmAutoBuild.sh" || [[ -f "/builddir/.bashrc" ]] && chmod 777 "/builddir/.bashrc" && source "/builddir/.bashrc";'
645
646 #(( $# == 0 )) && cmdType='--shell /bin/bash' || cmdType='--chroot' && inputCmds='/bin/bash -c '"'"'if [[ -f "/usr/local/bin/my-scripts/srpmAutoBuild.sh" ]]; then chmod 777 "/usr/local/bin/my-scripts/srpmAutoBuild.sh" && source "/usr/local/bin/my-scripts/srpmAutoBuild.sh"; elif [[ -f "/builddir/.bashrc" ]]; then chmod 777 "/builddir/.bashrc" && source "/builddir/.bashrc"; fi; sleep 1; srpmAutoBuild_setEnvVars; '"${*}"''"'"''
647 (( $# == 0 )) && cmdType='--shell /bin/bash' || cmdType='--chroot' && inputCmds='/bin/su -p --session-command "if [[ -f \"/usr/local/bin/my-scripts/srpmAutoBuild.sh\" ]]; then chmod 777 \"/usr/local/bin/my-scripts/srpmAutoBuild.sh\" && source \"/usr/local/bin/my-scripts/srpmAutoBuild.sh\"; elif [[ -f \"/builddir/.bashrc\" ]]; then chmod 777 \"/builddir/.bashrc\" && source \"/builddir/.bashrc\"; fi; sleep 1; srpmAutoBuild_setEnvVars; '"${*}"'"'
648
649 mock -r "$(srpmAutoBuild_getMockName)" --enable-network --old-chroot ${cmdType} "${inputCmds}"
650
651 # || eval $(echo "mock -r \$(srpmAutoBuild_getMockName)\" --old-chroot --chroot $(echo "${*}" | sed -E s/'-+file=(("[^"]*")|('"'"'[^'"'"']*'"'"')|([^"'"'"'][^ ]*))'/'\< \<\(\1\)'/g)")
652}
653
654
655srpmAutoBuild_mock-chroot() {
656 # same ad srpmAutoBuild_downloadBuildableSRPMs, but start by mounting/binding ${LOCALREPO_DIR} to mock and end by umounting it
657
658 srpmAutoBuild_mock-bind-localrepo
659 (( $# == 0 )) && srpmAutoBuild_mock-chroot0 || srpmAutoBuild_mock-chroot0 "${*}"
660 srpmAutoBuild_mock-umount-localrepo
661}
662
663# # # # # # # # # # # # # CODES TO INITIALIZE / SETUP / COPY FILES INTO / CLEAN MOCK # # # # # # # # # # # # #
664
665srpmAutoBuild_mock-clean() {
666 # unmounts ${LOCALREPO_DIR} from mock, transfers built RPMs, source SRPMS and specfiles from mock into ${LOCALREPO_DIR}, and then runs `mock -r <...> --clean`
667
668 # if mock doesnt exist it doesnt need to be cleaned
669 $(srpmAutoBuild_existMock) || return
670
671 srpmAutoBuild_copyFilesOutOfMock
672
673 [[ "$(pwd)" == ${MOCK_ROOT_DIR%/}* ]] && cd / && cd ~/
674
675 srpmAutoBuild_mock-force-umount-localrepo
676
677 mock -r "$(srpmAutoBuild_getMockName)" --scrub=all
678 mock -r "$(srpmAutoBuild_getMockName)" --clean
679}
680
681
682srpmAutoBuild_mock-init() {
683 # cleans, initialized, and sets up mock (including copying required scripts and setting up ~/.bashrc)
684 # if passed flag '-nc' or '--no-clean' or '--no-clear', then the function will initiate mock if it doesnt exist but if it does exist it will be left as-is
685
686 local noCleanFlag=0
687 ! srpmAutoBuild_existMock && noCleanFlag=1
688 (( $# > 0 )) && [[ ${1,,} =~ ^-+no?-?c(lea[nr])$ ]] && noCleanFlag=1 && shift 1
689
690 (( $noCleanFlag == 1 )) && echo "Not cleaning mock prior to initialization" >&2
691
692 srpmAutoBuild_setEnvVars
693
694 (( $noCleanFlag == 0 )) && srpmAutoBuild_mock-force-umount-localrepo && srpmAutoBuild_mock-clean
695
696 ( (( $noCleanFlag == 1 )) && srpmAutoBuild_existMock ) || mock -r "$(srpmAutoBuild_getMockName)" -r "$(srpmAutoBuild_getMockName)" --copyin "/etc/yum.repos.d" --init
697
698 if (( $# > 0 )); then
699 local copyItems=""
700 local buildScriptFlags=""
701
702 while (( $# > 0 )); do
703 ( [[ -d "${1}" ]] || [[ -f "${1}" ]] ) && copyItems="${copyItems} ${1}" || buildScriptFlags="${buildScriptFlags} ${1}"
704 shift 1
705 done
706
707 srpmAutoBuild_copyFilesIntoMock ${copyItems}
708 srpmAutoBuild_generateBuildScripts ${buildScriptFlags}
709 else
710 srpmAutoBuild_copyFilesIntoMock
711 srpmAutoBuild_generateBuildScripts
712 fi
713
714 srpmAutoBuild_mock-bind-localrepo
715
716 if [[ -f "${MOCK_ROOT_DIR}/usr/local/bin/my-scripts/srpmAutoBuild.sh" ]]; then
717
718 local bashrcAdd=""
719
720 bashrcAdd="$(echo -e "\n[[ -f \"/usr/local/bin/my-scripts/srpmAutoBuild.sh\" ]] && chmod 777 \"/usr/local/bin/my-scripts/srpmAutoBuild.sh\" && source \"/usr/local/bin/my-scripts/srpmAutoBuild.sh\" && srpmAutoBuild_setEnvVars \n")"
721
722 echo "$(echo "$(cat "${MOCK_ROOT_DIR}/builddir/.bashrc" | sed -z -E s/"$(srpmAutoBuild_escapeRegexChars --newline-mod "${bashrcAdd}")"//g)"; echo "${bashrcAdd}")" > "${MOCK_ROOT_DIR}/builddir/.bashrc"
723
724 fi
725
726}
727
728
729srpmAutoBuild_mock-makecache() {
730 local cmdOut=""
731 local nn=""
732
733 cmdOut="$(srpmAutoBuild_mock-chroot0 'dnf makecache' 2>&1)"
734 if [[ -n "$(echo "${cmdOut}" | tail -n 1)" ]] && [[ -n "$(echo "${cmdOut}" | tail -n 1 | grep -E '^Error\: Failed to synchronize cache for repo')" ]]; then
735
736 echo "Initial attempt to make dnf cache in mock failed. The code will now try cleaning and re-generating the local repository data + cache info and will then try making the mock dnf cache again."
737
738 srpmAutoBuild_mock-force-umount-localrepo
739 srpmAutoBuild_mock-chroot0 'dnf clean all' 2>/dev/null
740 dnf clean all
741 localrepo_updateDatabase --clean
742 srpmAutoBuild_mock-bind-localrepo
743
744 for nn in {repodata,cache,drpms,built,downloaded,source}; do
745 ( chmod -R 777 "$(find "${MOCK_ROOT_DIR%/}/${LOCALREPO_DIR}" -type d -name "${nn}")" 2>/dev/null )
746 done
747
748 cmdOut="$(srpmAutoBuild_mock-chroot0 'dnf makecache' 2>&1)"
749
750 [[ -n "$(echo "${cmdOut}" | tail -n 1)" ]] && [[ -n "$(echo "${cmdOut}" | tail -n 1 | grep -E '^Error\: Failed to synchronize cache for repo')" ]] && echo -e "\n\nWARNING: an unknown error is preventing a repo from syncing. srpmAutoBuild functions will likely fail until this is fixed."
751
752 fi
753}
754
755
756srpmAutoBuild_mock-build() {
757 # calls "srpmAutoBuild_mock-chroot 'srpmAutobuild_build ${*}'" and will, if needed, initialize mock if it is currently uninitialized.
758 # this allows one to call srpmAutoBuild_build from the hoist OS without needing to deal with mock setup or chroot
759 # by default it will not clean / re-initialize mock. Use flag '-c' or '--clean' to force this behavior.
760 # note that this flag MUST be the 1st input - all additional inputs are passed on to srpmAutobuild_build
761 # also note that, if called from within mock, this function will pass ALL inputs to srpmAutoBuild_build, and wont call srpmAutoBuild_mock-chroot
762 # If there are no inputs (or the only input is '-c' / '--clean') - srpmAutoBuild_build will build any SRPMs / specfiles in ${RPM_BUILD_DIR}/{SRPMS,SPECS}
763
764 if srpmAutoBuild_isMock; then
765 echo "RUNNING IN MOCK"
766 (( $# > 0 )) && srpmAutoBuild_build "${@}" && return
767 (( $# == 0 )) && srpmAutoBuild_build ${RPM_BUILD_DIR}/SRPMS/*.src.rpm ${RPM_BUILD_DIR}/SPECS/*.spec && return
768 else
769 echo "RUNNING IN HOST OS"
770 fi
771
772 (( $# > 0 )) && [[ ${1,,} =~ ^-+c(lean)?$ ]] && shift 1 && srpmAutoBuild_mock-clean
773
774 srpmAutoBuild_existMock || srpmAutoBuild_mock-init
775
776 (( $# > 0 )) && srpmAutoBuild_mock-chroot 'srpmAutoBuild_build '"${*}"'' && return
777 (( $# == 0 )) && srpmAutoBuild_mock-chroot 'srpmAutoBuild_build ${RPM_BUILD_DIR}/SRPMS/*.src.rpm ${RPM_BUILD_DIR}/SPECS/*.spec' && return
778
779}
780
781
782srpmAutoBuild_existMock() {
783 # returns true (exit status 0) is mock has been initialized and false (exit status 1) if it hasnt
784
785 srpmAutoBuild_isMock && return 0
786 [[ -d "${MOCK_ROOT_DIR}" ]] && return 0
787 srpmAutoBuild_isNotEmpty "${MOCK_ROOT_DIR}" && return 0 || return 1
788}
789
790
791srpmAutoBuild_copyFilesIntoMock() {
792 # copies needed scripts into mock. By default "${MOCK_ROOT_DIR}/usr/local/bin/my-scripts/" is always copied. Anyfunction inputs passed that are valid files or directories will be copied as well.
793
794 # make sure we have mock root directory
795 srpmAutoBuild_setEnvVars
796
797 local -a copyItems
798 local noScriptsFlag=0
799 local noCacheFlag=1
800
801 if (( $# > 0 )); then
802
803 if [[ ${1} =~ ^-+((n[dsc])|(no-?((default)|(cache)|(script))(-?copy)?)) ]]; then
804
805 [[ ${1} =~ ^-+((n[ds])|(no-?((default)|(script))(-?copy)?)) ]] && noScriptsFlag=1
806 [[ ! ${1} =~ ^-+((n[dc])|(no-?((default)|(cache))(-?copy)?)) ]] && noCacheFlag=0
807
808 shift 1
809 fi
810
811 copyItems=($(echo "${@}"))
812
813 # ensure directories exist and copy over srpmAutoBuild
814 (( $noScriptsFlag == 0)) && [[ -d "/usr/local/bin/my-scripts" ]] && copyItems[${#copyItems[@]}]="/usr/local/bin/my-scripts"
815 (( $noCacheFlag == 0)) && [[ -d "/var/cache/dnf" ]] && copyItems[${#copyItems[@]}]="/var/cache/dnf"
816
817 fi
818
819 copyItems[${#copyItems[@]}]="/usr/local/bin/my-scripts"
820 copyItems[${#copyItems[@]}]="/etc/yum.repos.d"
821
822 for nn in "${copyItems[@]}"; do
823
824 if [[ -d "${nn}" ]] || [[ -f "${nn}" ]]; then
825
826 nn="${nn%/}"
827 echo "Copying: \"${nn}\" --> \"${MOCK_ROOT_DIR}${nn}\""
828
829 [[ -d "${MOCK_ROOT_DIR}${nn%/*}" ]] || mkdir --parents "${MOCK_ROOT_DIR}${nn%/*}"
830 chmod -R 777 "${MOCK_ROOT_DIR}/${nn%/*}" "${nn}"
831
832 [[ -d "${nn}" ]] && ( [[ -d "${MOCK_ROOT_DIR}${nn}" ]] && \cp -rf ${nn}/* "${MOCK_ROOT_DIR}${nn}/" || \cp -rf "${nn}" "${MOCK_ROOT_DIR}${nn%/*}/" ) || ( [[ -f "${nn}" ]] && cp -f "${nn}" "${MOCK_ROOT_DIR}${nn}" )
833
834 fi
835
836 done
837
838}
839
840srpmAutoBuild_copyFilesOutOfMock() {
841 srpmAutoBuild_setEnvVars
842
843 [[ -d "${LOCALREPO_DIR}/built/NEW" ]] || mkdir --parents "${LOCALREPO_DIR}/built/NEW"
844 [[ -n $(find "${MOCK_ROOT_DIR}/builddir/build/RPMS/" -type f -name "*.rpm") ]] && \cp -au $(find "${RPM_BUILD_DIR}//RPMS/" -type f -name "*.rpm") "${LOCALREPO_DIR}/built/NEW/"
845
846 [[ -d "${LOCALREPO_DIR}/source/NEW" ]] || mkdir --parents "${LOCALREPO_DIR}/source/NEW"
847 [[ -n $(find "${MOCK_ROOT_DIR}/builddir/build/SRPMS/" -type f -name "*.src.rpm") ]] && \cp -au $(find "${RPM_BUILD_DIR}/SRPMS/" -type f -name "*.src.rpm") "${LOCALREPO_DIR}/source/NEW/"
848
849 [[ -d "${LOCALREPO_DIR}/.MISC/FROM_MOCK/SPECS" ]] || mkdir --parents "${LOCALREPO_DIR}/.MISC/FROM_MOCK/SPECS"
850 [[ -d "${LOCALREPO_DIR}/.MISC/FROM_MOCK/SPECS_OLD" ]] && \rm -rf "${LOCALREPO_DIR}/.MISC/FROM_MOCK/SPECS_OLD"
851 mkdir "${LOCALREPO_DIR}/.MISC/FROM_MOCK/SPECS_OLD"
852 [[ -n $(find "${LOCALREPO_DIR}/.MISC/FROM_MOCK/SPECS" -name "*.spec") ]] && \mv -f ${LOCALREPO_DIR}/.MISC/FROM_MOCK/SPECS/* "${LOCALREPO_DIR}/.MISC/FROM_MOCK/SPECS_OLD/"
853 [[ -n $(find "${RPM_BUILD_DIR}/SPECS/" -type f -name "*.spec") ]] && \cp -af ${RPM_BUILD_DIR}/SPECS/* "${LOCALREPO_DIR}/.MISC/FROM_MOCK/SPECS/"
854
855 [[ -f "${RPM_BUILD_DIR}/.STATUS" ]] && \cp -af "${RPM_BUILD_DIR}/.STATUS" "${LOCALREPO_DIR}/.MISC/FROM_MOCK/.STATUS"
856 [[ -f "${RPM_BUILD_DIR}/.STATUS_1" ]] && \cp -af "${RPM_BUILD_DIR}/.STATUS_1" "${LOCALREPO_DIR}/.MISC/FROM_MOCK/.STATUS_1"
857 [[ -f "${RPM_BUILD_DIR}/.STATUS_2" ]] && \cp -af "${RPM_BUILD_DIR}/.STATUS_2" "${LOCALREPO_DIR}/.MISC/FROM_MOCK/.STATUS_2"
858
859}
860
861srpmAutoBuild_generateBuildScripts() {
862 # produce scripts in the mock environment to call to start main and secondary build run with a single command
863 # any function inputs are assumed to be FLAGS for srpmAutoBuild_build and will be added to the start of the srpmAutoBuild_build function call
864
865 srpmAutoBuild_setEnvVars
866
867 local autoBuildCmdArgs=""
868 #local autoBuildCmd2=""
869
870 (( $# > 0 )) && autoBuildCmdArgs="${*}"
871
872 [[ -f "${MOCK_ROOT_DIR}/build-main.sh" ]] && chmod 777 "${MOCK_ROOT_DIR}/build-main.sh" && \rm -f "${MOCK_ROOT_DIR}/build-main.sh"
873 [[ -f "${MOCK_ROOT_DIR}/build-secondary.sh" ]] && chmod 777 "${MOCK_ROOT_DIR}/build-secondary.sh" && \rm -f "${MOCK_ROOT_DIR}/build-secondary.sh"
874
875 touch "${MOCK_ROOT_DIR}/build-main.sh" && chmod 777 "${MOCK_ROOT_DIR}/build-main.sh"
876 touch "${MOCK_ROOT_DIR}/build-secondary.sh" && chmod 777 "${MOCK_ROOT_DIR}/build-secondary.sh"
877
878 # [[ -d "${MOCK_ROOT_DIR}/builddir/" ]] || mkdir --parents "${MOCK_ROOT_DIR}/builddir/"
879
880 #autoBuildCmd2="$(echo "$(echo "${autoBuildCmd}" | sed -E s/'^(-+r(everse)?)?((.*[^\-])-+r(everse)?)*(.*[^\-])-+r(everse)?(.*)$'/'\4\6'/ | sed -E s/'^((.*[^\-])-+n(a|(o-?a(uto(-?match)?)?)))*(.*)$'/'\2\7'/ | sed -E s/'^ *([^ ].*[^ ]) *$'/'\1'/ | sed -E s/' +'/' '/) --reverse --no-auto-match")"
881
882cat << EOF > "${MOCK_ROOT_DIR}/build-main.sh"
883#!/bin/bash
884
885sleep 1
886
887# source srpmAutoBuild
888[[ -f "/usr/local/bin/my-scripts/srpmAutoBuild.sh" ]] && chmod 777 "/usr/local/bin/my-scripts/srpmAutoBuild.sh" && source "/usr/local/bin/my-scripts/srpmAutoBuild.sh" || [[ -f "/builddir/.bashrc" ]] && chmod 777 "/builddir/.bashrc" && source "/builddir/.bashrc"
889
890sleep 1
891
892# build all SRPMS
893srpmAutoBuild_build --build-main ${autoBuildCmdArgs} \${RPM_BUILD_DIR}/SRPMS/*.src.rpm
894
895# dont close window automatically
896echo -e "\n\n\nBUILD RUN #1 HAS FINISHED \n\n"
897exitVar="" && read -e -p "Press 'ENTER' to close this window" exitVar
898
899EOF
900
901cat << EOF > "${MOCK_ROOT_DIR}/build-secondary.sh"
902#!/bin/bash
903
904sleep 10
905
906# source srpmAutoBuild
907[[ -f "/usr/local/bin/my-scripts/srpmAutoBuild.sh" ]] && chmod 777 "/usr/local/bin/my-scripts/srpmAutoBuild.sh" && source "/usr/local/bin/my-scripts/srpmAutoBuild.sh" || [[ -f "/builddir/.bashrc" ]] && chmod 777 "/builddir/.bashrc" && source "/builddir/.bashrc"
908
909sleep 1
910
911localTimeoutLimit=1800
912
913echo -e "\n\nNOTICE: This build instance will remain idle until the main build run has finished instsalling all dependencies and generated all required specfiles from SRPMS. \nAt that point, it will begin to build the specfiles along with the main build instance, but going in the opposite order (i.e., from Z --> A instead of from A --> Z). \nIf, however, this build instance has not started in the next \$((( ( \$localTimeoutLimit ) / 60 ))) minutes, it will start without waiting for confirmation from the main build instance. \n"
914
915sleep 5
916
917# wait for indicator that primary run has built all specfiles, or timeout is reached
918tt=0
919hh=0
920while (( \$tt < \$localTimeoutLimit )) && [[ -f "\${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" ]]; do
921
922 sleep 1
923
924 ((tt++))
925 ((hh++))
926
927 if (( \$tt == \$localTimeoutLimit )); then
928
929 echo -e "\nTIMEOUT LIMIT REACHED. Would you like to add more time? \n\nn[o] --> dont add more time, start 2nd build run immediately. \ny[es] --> (DEFAULT) add 5 minutes to clock \n[0-9]+ --> add the specified number of minutes to the clock \n\n(timeout is 30 seconds)\n"
930 read -ie -p "Response (Y/n/#): " -t 30 extendTimeoutResponse
931
932 if [[ \${extendTimeoutResponse,,} =~ ^no?$ ]]; then
933 extendTimeoutResponse=0
934
935 elif ! [[ \${extendTimeoutResponse} =~ ^[0-9]+$ ]]; then
936 extendTimeoutResponse=300
937 fi
938
939 (( \$extendTimeoutResponse > 0 )) && localTimeoutLimit=\$((( \${localTimeoutLimit} + \${extendTimeoutResponse} ))) && echo -e "\nADDING \${extendTimeoutResponse} SECONDS TO TIMEOUT \nNEW TIMEOUT IS \$((( \${localTimeoutLimit} / 60 ))) MINUTES \n\n"
940 fi
941
942 (( \$hh == 60 )) && echo "\$((( \$tt / 60 ))) minute(s) elapsed. There are \$((( ( \$localTimeoutLimit - \$tt ) / 60 ))) minute(s) remaining until timeout is reached" && hh=0;
943
944done
945
946echo "NOW STARTING TO BUILD SPECFILES INTO RPMS"
947
948# build all SPECS
949srpmAutoBuild_build --build-secondary ${autoBuildCmdArgs} --reverse --no-auto-match \${RPM_BUILD_DIR}/SPECS/*.spec
950
951# dont close window automatically
952echo -e "\n\n\nBUILD RUN #2 HAS FINISHED \n\n"
953exitVar="" && read -e -p "Press 'ENTER' to close this window" exitVar
954
955EOF
956
957 sync
958
959 chmod 777 "${MOCK_ROOT_DIR}/build-main.sh" "${MOCK_ROOT_DIR}/build-secondary.sh"
960
961}
962
963
964# # # # # # # # CODES TO ANALYSE WHICH [S]RPMS HAVE BEEN BUILT / HAVENT BEEN BUILT / HAVE UPDATES # # # # # # # #
965# # # # # # # # # # # # # AND DOWNLOAD THE SRPMS THAT ARE AVAILABLE AND NOT YET BUILT # # # # # # # # # # # # #
966
967srpmAutoBuild_mock-downloadSRPMs() {
968 # moves to rpm build tree SRPM directors, downloads srpms with srpmAutoBuild_downloadBuildableSRPMs, then moves back to starting directory
969 srpmAutoBuild_rootUserCheck
970
971 (( $# > 0 )) && [[ ${1,,} =~ -+r(efresh(-?cache)?) ]] && dnf --refresh makecache --enablerepo='*source*' --disablerepo='*testing*'
972
973 srpmAutoBuild_setRpmBuildDir
974
975 cd "${RPM_BUILD_DIR}/SRPMS"
976
977 [[ ${1,,} =~ ^-+enable(-?all)?-?repos?$ ]] && srpmAutoBuild_downloadBuildableSRPMs "${1}" || srpmAutoBuild_downloadBuildableSRPMs
978
979 cd "${OLDPWD}"
980}
981
982
983srpmAutoBuild_listUnbuiltRPMs() {
984 # lists any installed rpms that there isnt a built rpm found for (see srpmAutoBuild_listBuiltSRPMs)
985
986 if (( $# > 0 )) && [[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?(\+a(rch(itecture)?)?)?$ ]]; then
987 echo "$(diff --width=512 -ywd --suppress-common-lines <(srpmAutoBuild_listInstalledRPMs "${1}") <(srpmAutoBuild_listBuiltRPMs "${1}") | grep -E '[\<\|]' | sed -E s/'^([^\<\|]*[^ \t])[ \t]*[\<\|].*$'/'\1'/)"
988 else
989 echo "$(diff --width=512 -ywd --suppress-common-lines <(srpmAutoBuild_listInstalledRPMs) <(srpmAutoBuild_listBuiltRPMs) | grep -E '[\<\|]' | sed -E s/'^([^\<\|]*[^ \t])[ \t]*[\<\|].*$'/'\1'/)"
990 fi
991}
992
993
994srpmAutoBuild_listInstalledRPMs() {
995 # List RPMs installed in the system
996
997 if (( $# > 0 )) && [[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?$ ]]; then
998
999 echo "$(dnf list --installed | sed -E s/'^([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1'/ | sed -E s/'^(.*)\.[^\.]*$'/'\1'/; rpm -qia | grep -E '^Name' | sed -E s/'Name {8}\: (.*)$'/'\1'/)" | sort -u
1000
1001 elif (( $# > 0 )) && [[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?\+a(rch(itecture)?)?$ ]]; then
1002
1003 echo "$(dnf list --installed | sed -E s/'^([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1'/; rpm -qia | grep -E '^((Name {8}\:)|(Architecture\:))' | sed -zE s/'Name {8}\: ([^\n]*)\nArchitecture\: ([^\n]*)'/'\'1\.'\2'/g)" | sort -u
1004
1005 else
1006
1007 echo "$(dnf list --installed | sed -E s/'^([a-zA-Z0-9][^ \t]*)\.([^\. \t]*)([ \t]*([0-9]+\:)?)([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1-\5\.\2'/; rpm -qa)" | sort -u
1008
1009 fi
1010}
1011
1012
1013srpmAutoBuild_listUpgradeRPMs() {
1014 # lists all the RPMs that dnf indicates have an available update
1015
1016 local dnfInstalledList=""
1017
1018 dnfInstalledList="$(dnf list --installed)"
1019
1020 if (( $# > 0 )) && [[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?(\+a(rch(itecture)?)?)?$ ]]; then
1021
1022 echo "$( \
1023 dnf check-upgrade --bugfix --enhancement --newpackage --security | tail -n +2 | sed -zE s/'^(.*\n)Obsoleting Packages.*$'/'\1'/ | sed -E s/'^([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1'/ | sort -u; \
1024 dnf check-update --bugfix --enhancement --newpackage --security | tail -n +2 | sed -zE s/'^(.*\n)Obsoleting Packages.*$'/'\1'/ | sed -E s/'^([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1'/ | sort -u; \
1025 echo "$(diff -ywd --width=512 <(dnf check-upgrade) <(echo "${dnfInstalledList}") --suppress-common-lines | grep -E '[\<\|]' | sed -E s/'^([^ \t]*)[ \t].*$'/'\1'/ | sed -zE s/'^(.*\n)Obsoleting.*$'/'\1'/)" | sort -u | grep -E '[a-zA-Z0-9]' | sed -E s/'^([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1'/ | sort -u; \
1026 echo "$(diff -ywd --width=512 <(dnf check-update) <(echo "${dnfInstalledList}") --suppress-common-lines | grep -E '[\<\|]' | sed -E s/'^([^ \t]*)[ \t].*$'/'\1'/ | sed -zE s/'^(.*\n)Obsoleting.*$'/'\1'/)" | sort -u | grep -E '[a-zA-Z0-9]' | sed -E s/'^([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1'/ | sort -u; \
1027 )" | sed -E s/'^(.*)'"$([[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?\+a(rch(itecture)?)?$ ]] || echo '\.[^\.]*')"'$'/'\1'/ | sort -u
1028
1029 else
1030
1031 echo "$( \
1032 dnf check-upgrade --bugfix --enhancement --newpackage --security | tail -n +2 | sed -zE s/'^(.*\n)Obsoleting Packages.*$'/'\1'/ | sed -E s/'^([a-zA-Z0-9][^ \t]*)\.([^\. \t]*)([ \t]*([0-9]+\:)?)([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1-\5\.\2'/ | sort -u; sleep 1; \
1033 dnf check-update --bugfix --enhancement --newpackage --security| tail -n +2 | sed -zE s/'^(.*\n)Obsoleting Packages.*$'/'\1'/ | sed -E s/'^([a-zA-Z0-9][^ \t]*)\.([^\. \t]*)([ \t]*([0-9]+\:)?)([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1-\5\.\2'/ | sort -u; sleep 1; \
1034 echo "$(diff -ywd --width=512 <(dnf check-upgrade) <(echo "${dnfInstalledList}") --suppress-common-lines | grep -E '[\<\|]' | sed -E s/'^([a-zA-Z0-9][^ \t]*)\.([^\. \t]*)([ \t]*([0-9]+\:)?)([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1-\5\.\2'/ | sed -zE s/'^(.*\n)Obsoleting.*$'/'\1'/)" | sort -u | grep -E '[a-zA-Z0-9]' | sed -E s/'^([a-zA-Z0-9][^ \t]*)\.([^\. \t]*)([ \t]*([0-9]+\:)?)([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1-\5\.\2'/ | sort -u; sleep 1; \
1035 echo "$(diff -ywd --width=512 <(dnf check-update) <(echo "${dnfInstalledList}") --suppress-common-lines | grep -E '[\<\|]' | sed -E s/'^([a-zA-Z0-9][^ \t]*)\.([^\. \t]*)([ \t]*([0-9]+\:)?)([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1-\5\.\2'/ | sed -zE s/'^(.*\n)Obsoleting.*$'/'\1'/)" | sort -u | grep -E '[a-zA-Z0-9]' | sed -E s/'^([a-zA-Z0-9][^ \t]*)\.([^\. \t]*)([ \t]*([0-9]+\:)?)([a-zA-Z0-9][^ \t]*)[ \t].*$'/'\1-\5\.\2'/ | sort -u; sleep 1; \
1036 )" | sed -E s/'^(.*)\.[^\.]*$'/'\1'/ | sort -u
1037
1038 fi
1039}
1040
1041
1042srpmAutoBuild_listBuiltRPMs() {
1043 # determines which RPMs have already been built. This is determined by the presence of the built RPM in [a subdirectory of] any of the following 3 locations:
1044 # # ${RPM_BUILD_DIR}/RPMS
1045 # # ${MOCK_ROOT_DIR}${LOCALREPO_DIR}/built.
1046 # # ${LOCALREPO_DIR}/built
1047
1048 srpmAutoBuild_setRpmBuildDir
1049 local rpmBuiltList=""
1050
1051 if (( $# > 0 )) && [[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?$ ]]; then
1052
1053 rpmBuiltList="$(echo "$(
1054 [[ -d ${RPM_BUILD_DIR}/RPMS ]] && [[ -n $(find ${RPM_BUILD_DIR}/RPMS -type f -name "*.rpm") ]] && echo "$(rpm -qip $(find ${RPM_BUILD_DIR}/RPMS -type f -name "*.rpm") | grep -E '^Name {8}\: ' | sed -E s/'^.*\: *(.*)$'/'\1'/ | sort -u)"; \
1055 [[ -d ${LOCALREPO_DIR}/built ]] && [[ -n $(find ${LOCALREPO_DIR}/built -type f -name "*.rpm") ]] && echo "$(rpm -qip $(find ${LOCALREPO_DIR}/built -type f -name "*.rpm") | grep -E '^Name {8}\: ' | sed -E s/'^.*\: *(.*)$'/'\1'/ | sort -u)"; \
1056 )" | sort -u)"
1057
1058 elif (( $# > 0 )) && [[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?\+a(rch(itecture)?)?$ ]]; then
1059
1060 rpmBuiltList="$(echo "$(
1061 [[ -d ${RPM_BUILD_DIR}/RPMS ]] && [[ -n $(find ${RPM_BUILD_DIR}/RPMS -type f -name "*.rpm") ]] && echo "$(rpm -qip $(find ${RPM_BUILD_DIR}/RPMS -type f -name "*.rpm") | grep -E '^((Name {8}\:)|(Architecture\:))' | sed -zE s/'Name {8}\: ([^\n]*)\nArchitecture\: ([^\n]*)'/'\'1\.'\2'/g | sort -u)"; \
1062 [[ -d ${LOCALREPO_DIR}/built ]] && [[ -n $(find ${LOCALREPO_DIR}/built -type f -name "*.rpm") ]] && echo "$(rpm -qip $(find ${LOCALREPO_DIR}/built -type f -name "*.rpm") | grep -E '^((Name {8}\:)|(Architecture\:))' | sed -zE s/'Name {8}\: ([^\n]*)\nArchitecture\: ([^\n]*)'/'\'1\.'\2'/g | sort -u)"; \
1063 )" | sort -u)"
1064
1065 else
1066
1067 rpmBuiltList="$(echo "$(
1068 [[ -d ${RPM_BUILD_DIR}/RPMS ]] && [[ -n $(find ${RPM_BUILD_DIR}/RPMS -type f -name "*.rpm") ]] && echo "$(find ${RPM_BUILD_DIR}/RPMS -type f -name "*.rpm" | sed -E s/'^.*\/([^\/]*)\.rpm$'/'\1'/ | sort -u)"; \
1069 [[ -d ${LOCALREPO_DIR}/built ]] && [[ -n $(find ${LOCALREPO_DIR}/built -type f -name "*.rpm") ]] && echo "$(find ${LOCALREPO_DIR}/built -type f -name "*.rpm" | sed -E s/'^.*\/([^\/]*)\.rpm$'/'\1'/ | sort -u)"; \
1070 )" | sort -u)"
1071
1072# [[ -d ${MOCK_ROOT_DIR}${LOCALREPO_DIR}/built ]] && [[ -n $(find ${MOCK_ROOT_DIR}${LOCALREPO_DIR}/built -type f -name "*.rpm") ]] && echo "$(find ${MOCK_ROOT_DIR}${LOCALREPO_DIR}/built -type f -name "*.rpm" | sed -E s/'^.*\/([^\/]*)\.rpm$'/'\1'/ | sort -u)"; \
1073
1074 fi
1075
1076 echo "$(echo "${rpmBuiltList}" | grep -v -E '\%{.+\}'; [[ -n $(echo "${rpmBuiltList}" | grep -E '\%{.+\}') ]] && rpm --eval $(echo "${rpmBuiltList}" | grep -E '\%{.+\}'))" | sort -u
1077}
1078
1079
1080srpmAutoBuild_listBuiltSRPMs() {
1081 # Lists installed RPMs that were built on the system
1082
1083 [[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?\+a(rch(itecture)?)?$ ]] && srpmAutoBuild_getSRPM_fromRPM $(srpmAutoBuild_listBuiltRPMs "${1}") || srpmAutoBuild_getSRPM_fromRPM $(srpmAutoBuild_listBuiltRPMs)
1084
1085}
1086
1087
1088srpmAutoBuild_listUpgradeSRPMs() {
1089 # Lists installed RPMs that were NOT built on the system (i.e., were downloaded as pre-compiled RPMs)
1090
1091 [[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?\+a(rch(itecture)?)?$ ]] && srpmAutoBuild_getSRPM_fromRPM $(srpmAutoBuild_listUpgradeRPMs "${1}") || srpmAutoBuild_getSRPM_fromRPM $(srpmAutoBuild_listUpgradeRPMs)
1092
1093}
1094
1095srpmAutoBuild_getSRPM_fromRPM() {
1096 # determines the names of the source SRPMs needed to build the list of RPMs described in the in the function input(s)
1097
1098 (( $# > 0 )) && dnf info --best --skip-broken "${@}" | grep -E '^Source' | sed -E s/'^[^\:]*\:[ \t]*(.*)$'/'\1'/ | grep -v '^None$' | sort -u || echo ""
1099}
1100
1101
1102srpmAutoBuild_listExcludedSRPMs() {
1103 # any RPMs or SRPMs listed in ${RPM_BUILD_DIR}/.EXCLUDE will not be downloaded.
1104 # Note: If an RPM is listed its analogous SRPM will be blacklisted, even if that same SRPM can build other RPMs that were not explicitly excluded.
1105 # Note: this is not well tested, and may not work
1106
1107 srpmAutoBuild_setRpmBuildDir
1108
1109 [[ -f "${RPM_BUILD_DIR}/.EXCLUDE" ]] && [[ -n $(cat "${RPM_BUILD_DIR}/.EXCLUDE") ]] && echo "$( \
1110 [[ -n $(cat "${RPM_BUILD_DIR}/.EXCLUDE" | grep '.src.rpm$') ]] && echo "$(cat ${RPM_BUILD_DIR}/.EXCLUDE | grep '.src.rpm$')"; \
1111 [[ -n $(cat "${RPM_BUILD_DIR}/.EXCLUDE" | grep -v '.src.rpm$' | grep -v '.rpm$') ]] && echo "$(srpmAutoBuild_getSRPM_fromRPM $(echo "$(cat ${RPM_BUILD_DIR}/.EXCLUDE | grep -v '.src.rpm$' | grep -v '.rpm$')"))"; \
1112 )" | sed -E s/'^.*\/([^\/]*)$'/'\1'/ | grep -v "None" | sort -u
1113}
1114
1115
1116srpmAutoBuild_listDownloadRPMs() {
1117 # generate a list of RPMs to actually download SRPMs for. This is a combination of unbuilt (but available) SRPMS and SRPMs that have an updated version (vs the version that was built)
1118
1119 [[ ${1,,} =~ ^-+s((hort|imple)(-?names?))?(\+a(rch(itecture)?)?)?$ ]] && echo "$(srpmAutoBuild_listUnbuiltRPMs "${1}") $(srpmAutoBuild_listUpgradeRPMs "${1}")" | sort -u || echo "$(srpmAutoBuild_listUnbuiltRPMs) $(srpmAutoBuild_listUpgradeRPMs)" | sort -u
1120}
1121
1122srpmAutoBuild_listDownloadRPMs_ALL() {
1123 # generated a list of RPMs to actually download SRPMs for, using all 3 naming styles
1124
1125 echo "$(srpmAutoBuild_listDownloadRPMs; srpmAutoBuild_listDownloadRPMs -s; srpmAutoBuild_listDownloadRPMs -s+a)" | sort -u
1126}
1127
1128
1129srpmAutoBuild_downloadBuildableSRPMs() {
1130 # Download (to the current directory) all build-able SRPMs that are available. Try looking using both `dnf --download source <RPM names>` and `dnf download <SRPM names>`
1131
1132 srpmAutoBuild_setEnvVars
1133
1134 local rpmDownloadList1=""
1135 local rpmDownloadList2=""
1136 local rpmDownloadList3=""
1137 local rpmDownloadList=""
1138 local srpmDownloadList=""
1139
1140 rpmDownloadList1="$(srpmAutoBuild_listDownloadRPMs)"
1141 rpmDownloadList2="$(srpmAutoBuild_listDownloadRPMs -s)"
1142 rpmDownloadList3="$(srpmAutoBuild_listDownloadRPMs -s+a)"
1143
1144 rpmDownloadList="$(echo ${rpmDownloadList1} ${rpmDownloadList2} ${rpmDownloadList3})"
1145
1146 srpmDownloadList="$(srpmAutoBuild_getSRPM_fromRPM ${rpmDownloadList} | sed -E s/'^(.*)\.rpm'/'\1'/ | sort -u)"
1147
1148 if [[ ${1,,} =~ ^-+enable(-?all)?-?repos?$ ]] ; then
1149 [[ -n ${rpmDownloadList} ]] && dnf download --source --best --skip-broken -y --enablerepo=[a-z]* $([[ ${1,,} =~ ^-+enable-?all-?repos?$ ]] || echo '--disablerepo=*testing*') ${rpmDownloadList}
1150 [[ -n ${srpmDownloadList} ]] && dnf download --best --skip-broken -y --enablerepo=[a-z]* $([[ ${1,,} =~ ^-+enable-?all-?repos?$ ]] || echo '--disablerepo=*testing*') ${srpmDownloadList}
1151 else
1152 [[ -n ${rpmDownloadList} ]] && dnf download --source --best -y --skip-broken ${rpmDownloadList}
1153 [[ -n ${srpmDownloadList} ]] && dnf download --best -y --skip-broken ${srpmDownloadList}
1154 fi
1155
1156 #rpmDownloadList_wget="${rpmDownloadList1}"
1157 #archListA=(${VALID_ARCH_LIST})
1158 #for nn in "${archListA[@]}"; do
1159 # rpmDownloadList_wget="${rpmDownloadList_wget//.${nn}/}"
1160 #done
1161 #rpmDownloadList_wget="$(echo "${rpmDownloadList_wget}" | sed -E s/'^(.*)\.rpm$'/'\1'/ | sed -E s/'^(.*)\.src$'/'\1'/)"
1162
1163 #$(echo "${rpmDownloadList_wget}" | sed -E s/'^(.*)-([^-]*)-([^\. t]*(\.[^\. \t]*)*)[ \t]*$'/'wget https\:\/\/kojipkgs\.fedoraproject\.org\/\/packages\/\1\/\2\/\3\/src\/ -O \1-\2\.\3\.src\.rpm\; '/ | grep 'https')
1164
1165 #eval $(echo "${rpmDownloadList_wget}" | sed -E s/'^((.*)-([^-]*)-([^\.]*\.[^\.]*)\.src)(\.rpm)?$'/'wget https\:\/\/kojipkgs\.fedoraproject\.org\/\/packages\/\2\/\3\/\4\/src\/\1\.rpm\;'/)
1166
1167 #eval $(echo "${rpmDownloadList_wget}" | sed -E s/'^(.*)-([^-]*)-([^\.]*\.[^\.]*)[ \t]*$'/'https\:\/\/kojipkgs\.fedoraproject\.org\/\/packages\/\1\/\2\/\3\/src\/\1-\2\.\3\.src\.rpm\;'/ | sed -E s/' '//g | sed -E s/'^(.*)$'/'wget '"'"'\1'"'"''/)
1168
1169 #dnf download --source --skip-broken $(srpmAutoBuild_listDownloadRPMs) $(echo "$(srpmAutoBuild_listBuiltSRPMs)" "$(srpmAutoBuild_listExcludedSRPMs)" | sort -u | sed -E s/'^(.*)\.src\.rpm$'/'-x \1'/)
1170 #dnf download --source --skip-broken $(diff -ywd --width=512 <(dnf check-upgrade) <(dnf list --installed) --suppress-common-lines | grep -E '[\<\|]' | sed -E s/'^([^ \t]*)[ \t].*$'/'\1'/ | sed -zE s/'^(.*)\nObsoleting.*$'/'\1\n'/)
1171}
1172
1173srpmAutoBuild_listNewestRPMs() {
1174 # Scans through the SRPMs in the current directory (or the directory specified by function inputs, if it exists and it valid)
1175 # and returns the names of the newest version of each SRPM package. Useful to filter out old SRPMs mixed with new ones.
1176 #
1177 # scans $(pwd) unless input function exists and is a existing valid directory.
1178 #
1179 # make 1st input '-r' to scan directories recursively. otherwise only the top level of the specified directories are scanned
1180 #
1181 # optional: hard code your choosen info function. using 'infoFunctionType' variable. valid options are 'getInfo' and 'getRpmNames'.
1182 # 'getInfo' is more robust (especially for filename inputs), but is slower (especially for directory inputs)
1183 # speed: getInfo is ~1/2 the speed for filelist inputs and ~1/10 the speed for directory inputs.
1184 # default is to use 'getInfo' for file list inputs and 'getRpmNames' for directory inputs
1185
1186
1187 local -a pkgAllA
1188 local pkgAll=""
1189 local pkgCur=""
1190 #local pkgNew=""
1191 local nameCur=""
1192 local nameNew=""
1193 local rFlag=0
1194
1195 local infoFunctionType=""
1196 # infoFunctionType='getInfo'
1197 # infoFunctionType='getRpmNames'
1198
1199 if [[ "${infoFunctionType}" != 'getInfo' ]] && [[ "${infoFunctionType}" != 'getRpmNames' ]]; then
1200 [[ -d "${*}" ]] && infoFunctionType='getRpmNames' || infoFunctionType='getInfo'
1201 fi
1202
1203 (( $# > 0 )) && [[ ${1,,} =~ ^-+r$ ]] && rFlag=1 && shift 1
1204
1205 pkgAllA=($(echo "$(eval "$(echo "${@}" | grep -E '\.rpm$' | sed -E s/'^(.*)$'/'\[\[ -f "\1" \]\] \&\&'/ | sed -zE s/'\n'/' '/g | sed -zE s/'^(.*) \&\& $'/'\1'/)" && echo "${@}" | grep -E '\.rpm$' || find "$( (( $# > 0 )) && [[ -d "${*}" ]] && echo "${*}" || echo "$(pwd)" )" $( (( $rFlag == 0 )) && echo -n '-maxdepth 1' || echo -n '' ) -type f -name "*.rpm" | sort -V)"))
1206
1207 pkgCur="${pkgAllA[0]}"
1208 pkgAll=""
1209
1210 if [[ "${infoFunctionType}" == 'getRpmNames' ]]; then
1211 local -a nameAll=""
1212 local kk=1
1213
1214 if [[ -d "${*}" ]]; then
1215 nameAll=($(srpmAutoBuild_getRpmNames "$(echo "${pkgAllA[*]}" | sed -E s/'\.rpm \/'/'\.rpm\n\/'/g | sed -E s/'^(.*)\/[^\/]+$'/'\1'/ | sort -u)"))
1216 else
1217 nameAll=($(srpmAutoBuild_getRpmNames "${pkgAllA[@]}"))
1218 fi
1219
1220 nameCur="${nameAll[0]}"
1221 nameAll[0]=""
1222 nameAll=( "${nameAll[@]}" )
1223
1224 else
1225 nameCur="$(srpmAutoBuild_getInfo -n -v -a "$(echo -n "${pkgCur}")")"
1226 fi
1227
1228 for nn in "${pkgAllA[@]}"; do
1229 [[ "${infoFunctionType}" == 'getInfo' ]] && nameNew="$(srpmAutoBuild_getInfo -n -v -a "$(echo -n "${nn}")")"
1230 [[ "${infoFunctionType}" == 'getRpmNames' ]] && nameNew="${nameAll[$kk]}" && ((kk++))
1231
1232 if [[ "${nameCur}" != "${nameNew}" ]]; then
1233 pkgAll="$(echo "$(echo "${pkgAll}"; echo "${pkgCur##*/}" | sort -V | tail -n 1)")"
1234 pkgCur="${nn}"
1235 nameCur="${nameNew}"
1236 else
1237 pkgCur="$(echo "$(echo "${pkgCur}"; echo "${nn}")")"
1238 fi
1239 done
1240
1241 pkgAll="$(echo "$(echo "${pkgAll}"; echo "${pkgCur##*/}" | sort -V | tail -n 1)" | sort -u | sort -V)"
1242
1243 echo "${pkgAll}"
1244}
1245
1246srpmAutoBuild_listFunctionNames() {
1247 # lists all function names
1248 # flag '-s' / '-sab' / '--srpm[AutoBuild]' --> only list 'srpmAutoBuild_' functions
1249 # flag '-l' / '--localrepo' --> only list 'localrepo_' functions
1250 # default: list both 'srpmAutoBuild_' functions and 'localrepo_' functions
1251
1252 local filterString=""
1253
1254 (( $# > 0 )) && [[ ${1,,} =~ -+s((ab)?|(rpm(-?(auto)?(-?(build))))) ]] && filterString='srpmAutoBuild'
1255 (( $# > 0 )) && [[ ${1,,} =~ -+l((ocal)?-?r(epo)?)? ]] && filterString='localrepo'
1256 [[ -z "${filterString}" ]] && filterString='((srpmAutoBuild)|(localrepo))'
1257
1258 cat "/usr/local/bin/my-scripts/srpmAutoBuild.sh" | grep -E '^'"${filterString}"'_[^ ]+\(\) \{' | sed -E s/'^(.*)\(\) \{.*$'/'\1'/
1259}
1260
1261
1262srpmAutoBuild_searchFunctionNames() {
1263 # searches the list of function names for matching ones. Accepts globs
1264 # flag: '-n' --> dontadd newlines yto the response
1265
1266 local nn=""
1267 local useNewlines=1
1268
1269 (( $# > 0 )) && [[ "${1,,}" == "-n" ]] && useNewlines=0 && shift 1
1270
1271 (( $# == 0 )) && srpmAutoBuild_listFunctionNames && return
1272
1273 for nn in "${@}"; do
1274 (( $useNewlines == 1 )) && echo ""
1275 echo -n "$( srpmAutoBuild_listFunctionNames | grep -E "$(srpmAutoBuild_escapeRegexChars -g "${nn}")"; srpmAutoBuild_listFunctionNames | grep -F "${nn}" )" | sort -u
1276 (( $useNewlines == 1 )) && echo -e "\n--------------------------------------------------------------------------------\n"
1277 done
1278}
1279
1280
1281srpmAutoBuild_help() {
1282 # searches for the specified name and returns the header help text. accepts globs
1283
1284 #local funcNameList=""
1285 local inCur=""
1286 local -a funcNamesCur
1287 local funcNameCur0=""
1288
1289 #funcNameList="$(srpmAutoBuild_listFunctionNames)"
1290
1291 (( $# == 0 )) && echo -e "\n\nTo get help with a specific function, run 'srpmAutoBuild_help <functionName>'. \n\nRun 'srpmAutoBuild_listFunctionNames' and/or 'srpmAutoBuild_searchFunctionNames <...>' to see valid srpmAutoBuild_ and localrepo_ function names.\n\n" && sleep 2 && cat "/usr/local/bin/my-scripts/srpmAutoBuild.sh" | sed -zE s/'^([^\n]*(\n[ \t]*\#[^\n]*)*).*$'/'\1'/ && echo -e "\n\n" && return
1292
1293 for inCur in "${@}"; do
1294 echo ""
1295 funcNamesCur=("$(srpmAutoBuild_searchFunctionNames -n "${inCur}")")
1296
1297 if [[ -z "${funcNamesCur[*]}" ]]; then
1298 echo "Input not recognized as a valid 'srpmAutoBuild_' or 'localrepo_' function name"
1299 else
1300 for funcNameCur0 in "${funcNamesCur[@]}"; do
1301 cat "/usr/local/bin/my-scripts/srpmAutoBuild.sh" | sed -zE s/'^.*(\n'"$(srpmAutoBuild_escapeRegexChars "${funcNameCur0}")"'\(\) \{ *(\n[ \t]*(#[^\n]*)?)*).*$'/'\1'/
1302 echo ""
1303 done
1304 fi
1305
1306 echo -e "\n"
1307 (( $# > 0 )) && echo -e "--------------------------------------------------------------------------------\n\n"
1308 done
1309}
1310
1311
1312srpmAutoBuild_makeAliases() {
1313 # replace the leading "srpmAutoBuild" and "localrepo" in function names with something shorter
1314 # input #1 defines srpmAutoBuild replacement, default if missing is 'sab'
1315 # input #2 defines localrepo replacement, default if missing is 'lr'
1316
1317 local srpmAutoBuild_abbr=""
1318 local localrepo_abbr=""
1319
1320 (( $# < 1 )) && srpmAutoBuild_abbr="sab" || srpmAutoBuild_abbr="${1}"
1321 (( $# < 2)) && localrepo_abbr="lr" || localrepo_abbr="${2}"
1322
1323 [[ -n ${srpmAutoBuild_abbr} ]] && eval $(cat "/usr/local/bin/my-scripts/srpmAutoBuild.sh" | grep -E '^srpmAutoBuild_[^ ]+\(\) \{' | sed -E s/'^(.*)\(\) \{.*$'/'\1'/ | sed -E s/'^(srpmAutoBuild)(.*)$'/'alias '"$(srpmAutoBuild_escapeRegexChars "${srpmAutoBuild_abbr}")"'\2='"'"'\1\2'"'"';'/)
1324
1325 [[ -n ${localrepo_abbr} ]] && eval $(cat "/usr/local/bin/my-scripts/srpmAutoBuild.sh" | grep -E '^localrepo_[^ ]+\(\) \{' | sed -E s/'^(.*)\(\) \{.*$'/'\1'/ | sed -E s/'^(localrepo)(.*)$'/'alias '"$(srpmAutoBuild_escapeRegexChars "${localrepo_abbr}")"'\2='"'"'\1\2'"'"';'/)
1326}
1327
1328
1329srpmAutoBuild_setRpmBuildDir() {
1330 # determines top level of rpm tree. In mock this is at /builddir/build, otherwise it is at ~/rpmbuild
1331 # for non-standard rpm build dirs set + export RPM_BUILD_DIR manually. If RPM_BUILD_DIR has been set externally and exported as a global environment variable this will NOT overwrite it. UNLESS input Flag '-c' or '--clear' or '--clean' is used
1332 #
1333 # Note: behavior is as follows:
1334 # # (1.) check if RPM_BUILD_DIR exists, and if so about, else
1335 # # (2.) check if we are in mock, if so return /builddir/build, else
1336 # # (3.) check if mock filesystem exists, if so return ${MOCK_ROOT_DIR}/builddir/build, else
1337 # # (4.) return ${HOME}/rpmbuild
1338 #
1339 # Note: this will also set / export MOCK_ROOT_DIR, so if calling this function there is no need to call srpmAutoBuild_setMockRootDir also
1340
1341 local cleanFlag=""
1342
1343 [[ ${1,,} =~ ^-+c(lea[nr])?$ ]] && cleanFlag="-c"
1344 [[ -n "${RPM_BUILD_DIR}" ]] && ( ( srpmAutoBuild_isMock && [[ ${RPM_BUILD_DIR} == /var/lib/mock/* ]] ) || ( ! srpmAutoBuild_isMock && [[ ${RPM_BUILD_DIR} != /var/lib/mock/* ]] && [[ "${RPM_BUILD_DIR}" != "${HOME}/rpmbuild" ]] ) ) && cleanFlag="-c"
1345
1346 srpmAutoBuild_setMockRootDir "${cleanFlag}"
1347
1348 if [[ -z "${RPM_BUILD_DIR}" ]] || [[ "${cleanFlag}" == "-c" ]]; then
1349
1350 if srpmAutoBuild_isMock; then
1351 RPM_BUILD_DIR='/builddir/build'
1352 else
1353 [[ "${MOCK_ROOT_DIR}" != "NONE" ]] && RPM_BUILD_DIR="${MOCK_ROOT_DIR}/builddir/build" || RPM_BUILD_DIR="${HOME}/rpmbuild"
1354 fi
1355
1356 export RPM_BUILD_DIR
1357
1358 echo -e "\nRPM_BUILD_DIR set to: '${RPM_BUILD_DIR}'\n"
1359
1360 elif [[ "${RPM_BUILD_DIR}" == "${RPM_BUILD_DIR%/}" ]] || [[ "${RPM_BUILD_DIR}" == *'//'* ]]; then
1361
1362 RPM_BUILD_DIR="${RPM_BUILD_DIR//'//'/'/'}"
1363 RPM_BUILD_DIR="${RPM_BUILD_DIR%/}"
1364 export RPM_BUILD_DIR
1365
1366 fi
1367
1368 [[ -d "${RPM_BUILD_DIR}" ]] || srpmAutoBuild_setuptree
1369
1370}
1371
1372
1373srpmAutoBuild_isMock() {
1374 # determines if we are currently in mock or not
1375 # example usage: $(srpmAutoBuild_isMock) && $(commandToRunInMock) || $(commandToRunInHostOS)
1376
1377 (( $((( $( [[ "${PROMPT_COMMAND}" == *'<mock-chroot>'* ]] && echo 1 || echo 0 ) + $( [[ -n "$(env | grep 'PS1')" ]] && [[ "$(env | grep 'PS1')" == *'<mock-chroot>'* ]] && echo 1 || echo 0 ) ))) > 0 )) && return 0 || return 1
1378
1379}
1380
1381
1382
1383srpmAutoBuild_getMockName() {
1384 # get mock name. Should be something like '$(distro)-$(ver)-$(arch)' (ex: 'fedora-29-x86_64')
1385 # setr/export the environment variable 'SRPMAUTOBUILD_SETVERSION_MOCK' to force a specific mock version. Otherwise mock will be setup to use the same distro / os version / arch as the host system.
1386
1387 if [[ -n "${SRPMAUTOBUILD_SETVERSION_MOCK}" ]]; then
1388 [[ ! -d "/var/lib/mock/${SRPMAUTOBUILD_SETVERSION_MOCK}" ]] && [[ ! -f "/etc/mock/${SRPMAUTOBUILD_SETVERSION_MOCK}.cfg" ]] && echo -e "\n\nWARNING: The mock version set by environment variable SRPMAUTOBUILD_SETVERSION_MOCK does not appear to be a valid mock version installed on this system. \nsrpmAutoBuild will still attempt to use it. If this is an error, manually abourt code execution and either re-set/re-export or clear/remove SRPMAUTOBUILD_SETVERSION_MOCK \n" 1>&2
1389 echo "${SRPMAUTOBUILD_SETVERSION_MOCK}" && return
1390 fi
1391
1392 local distro=""
1393 distro="$(sed 's, release .*$,,g' /etc/system-release)"
1394
1395 echo "${distro,,}-$(uname -r | sed -E s/'.*\.fc([0-9]+\.[^\.]+)$'/'\1'/ | sed -E s/'\.'/'-'/)"
1396}
1397
1398
1399srpmAutoBuild_setMockRootDir() {
1400 # determines where the root of the mock environment is. This should return /var/lib/mock/*/root when run from from the main OS, and '/' when run from within mock. If MOCK_ROOT_DIR has been set externally and exported as a global environment variable this will NOT overwrite it.
1401
1402 local cleanFlag=""
1403
1404 [[ ${1,,} =~ ^-+c(lea[nr])?$ ]] && cleanFlag="-c"
1405
1406 [[ -n "${MOCK_ROOT_DIR}" ]] && ( ( srpmAutoBuild_isMock && [[ ${MOCK_ROOT_DIR} == /var/lib/mock/* ]] ) || ( ! srpmAutoBuild_isMock && [[ ${MOCK_ROOT_DIR} != /var/lib/mock/* ]] ) ) && cleanFlag="-c"
1407
1408 if [[ -z "${MOCK_ROOT_DIR}" ]] || [[ "${cleanFlag}" == "-c" ]]; then
1409
1410 srpmAutoBuild_isMock && MOCK_ROOT_DIR='' && export MOCK_ROOT_DIR || MOCK_ROOT_DIR="$(mock -r "$(srpmAutoBuild_getMockName)" -p | sed -E s/'^(.*)\/$'/'\1'/)" && export MOCK_ROOT_DIR
1411
1412 echo -e "MOCK_ROOT_DIR set to: '${MOCK_ROOT_DIR}'\n"
1413
1414 elif [[ "${MOCK_ROOT_DIR}" != "${MOCK_ROOT_DIR%/}" ]]; then
1415
1416 MOCK_ROOT_DIR="${MOCK_ROOT_DIR%/}" && export MOCK_ROOT_DIR
1417
1418 fi
1419
1420 #MOCK_ROOT_DIR="/var/lib/mock/fedora-$(uname -r | sed -E s/'.*\.fc([0-9]+\.[^\.]+)$'/'\1'/ | sed -E s/'\.'/'-'/)/root" && export MOCK_ROOT_DIR
1421}
1422
1423
1424srpmAutoBuild_setEnvVars() {
1425 # sets build environment variables + shortened aliases. These can be used, for example, to pass FLAGS about the system architecture and optimization level to gcc via the "CFLAGS/CPPFLAGS/CXXFLAGS/LDFLAGS" environment variables
1426 #
1427 # NOTE: any function inputs (except the flags listed below) will be added to the CFLAGS_DEFAULT variables specified below.
1428 # i.e., function inputs will be added to CFLAGS/CPPFLAGS/CXXFLAGS, but not LDFLAGS.
1429 # by default, LD flags only is set via the OFLAGS_DEFAULT, which sets default optimization level ('-O3', '-O2', etc)
1430 #
1431 # SPECIAL CASE : if the 1st input is the Flag '-c' or --clean' or '--clear', the default [CO]FLAGS_DEFAULT variables will not be used.
1432 #
1433 # ---------------------- FLAGS ----------------------
1434 #
1435 # DEFAULT behavior is to set CFLAGS/CPPFLAGS/CXXFLAGS/LDFLAGS + clear/re-set RPM_BUILD_DIR + set (if not already set) LOCALREPO_DIR
1436 # (note: use of '...clea[nr]' means you can use either '...clean' or '...clear')
1437 #
1438 # '-nc' or '--no-clea[nr]': if RPM_BUILD_DIR is already set, dont re-set it (so it has the same behavior as setting LOCALREPO_DIR)
1439 # '-ce' or '--clea[nr]-env': clear/re-set LOCALREPO_DIR (so it has the same behavior as setting RPM_BUILD_DIR)
1440 # '-c' or '--clea[nr]': do not use the default CFLAGS_DEFAULT and OFLAGS_DEFAULT when setting CFLAGS/CPPFLAGS/CXXFLAGS/LDFLAGS
1441 # This will clear LDFLAGS (i.e., set it to "") and will set CFLAGS/CPPFLAGS/CXXFLAGS to the function input(s) (minus flag(s))
1442 # If no additional function inputs are present (other than any flags), this will effectively un-set the CFLAGS/CPPFLAGS/CXXFLAGS variables completely
1443 # See below for more info (go to the line that says '# SET THESE, UNLESS YOU HAVE A SKYLAKE-X OR SKYLAKE-XEON CPU!!!')
1444 # '-cf' or '--clea[nr]-flags': this does the same as using '-c' or '--clean', and exists only to make it explicity clear that it controls setting [C|CXX|CPP|LD]FLAGS
1445 # '-ca' or '--clea[nr]-all': This is the same as setting both '-c(f)?'/'--clea[nr](-flags)?' and '-ce'/'-clea[nr]-env'
1446
1447 # Setup Environment Variables
1448
1449 local CFLAGS_DEFAULT=""
1450 local OFLAGS_DEFAULT=""
1451
1452 (( $# > 0 )) && [[ ${1,,} =~ ^-+no?-?c(lea[nr])?$ ]] && srpmAutoBuild_setRpmBuildDir || srpmAutoBuild_setRpmBuildDir -c
1453 (( $# > 0 )) && [[ ${1,,} =~ ^-+c(lea[nr])?-?((a(ll)?)|(e(nv)?))$ ]] && localrepo_setEnvVars -c || localrepo_setEnvVars
1454 (( $# > 0 )) && [[ ${1,,} =~ ^-+((no?-?c(lea[nr])?)|(c(lea[nr])?-?e(nv)?))$ ]] && shift 1
1455
1456 srpmAutoBuild_rpmbuildCheck
1457 srpmAutoBuild_makeAliases
1458
1459 if (( $# > 0 )) && [[ ${1,,} =~ ^-+c(lea[nr])?(-?((a(ll)?)|(f(lags?)?)))?$ ]]; then
1460 shift 1
1461
1462 else
1463 # SET THESE, UNLESS YOU HAVE A SKYLAKE-X OR SKYLAKE-XEON CPU!!!
1464 #
1465 # CFLAGS_DEFAULT apply to CFLAGS/CPPFLAGS/CXXFLAGS but not LDFLAGS
1466 # OFLAGS_DEFAULT apply to all 4 (CFLAGS/CPPFLAGS/CXXFLAGS/LDFLAGS)
1467 #
1468 # You can get better performance if you change these based on your hardware.
1469 # See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for more info.
1470
1471 if [[ -n "$(cat /proc/cpuinfo | grep 'avx512')" ]]; then
1472 # assume we have a skylake-x or skylake-xeon. This will become a worse and worse assumption as more avx512 processors are released, but for now it should be mostly correct.
1473 CFLAGS_DEFAULT="-m64 -march=skylake-avx512 -mtune=native -mcpu=skylake-avx512 -mprefer-vector-width=512 -mavx512f -mavx512vl -mavx512cd -mavx512bw -mavx512dq -masm=intel"
1474 OFLAGS_DEFAULT="-O3"
1475 else
1476 CFLAGS_DEFAULT="-march=native -mtune=generic"
1477 OFLAGS_DEFAULT="-O2"
1478 fi
1479
1480 [[ ${1,,} =~ ^-+((c(lea[nr])?-?((a(ll)?)|(e(nv)?)|(f(lags?)?)))|(no?-?c(lea[nr])?))$ ]] && shift 1
1481 fi
1482
1483 if (( $# > 0 )); then
1484 CFLAGS_DEFAULT="${CFLAGS_DEFAULT} ${*}"
1485 fi
1486
1487 CFLAGS="${CFLAGS_DEFAULT} ${OFLAGS_DEFAULT}"
1488 CPPFLAGS="${CFLAGS_DEFAULT} ${OFLAGS_DEFAULT}"
1489 CXXFLAGS="${CFLAGS_DEFAULT} ${OFLAGS_DEFAULT}"
1490 LDFLAGS="${OFLAGS_DEFAULT}"
1491
1492 export CFLAGS
1493 export CPPFLAGS
1494 export CXXFLAGS
1495 export LDFLAGS
1496
1497}
1498
1499
1500srpmAutoBuild_getTotalMem() {
1501 # grabs total system memory from /proc/meminfo. Output is in K[ilobytes] (same as used in /proc/meminfo )
1502
1503 cat "/proc/meminfo" | grep '^MemTotal' | sed -E s/'^[^0-9]*([0-9]*)[^0-9]**$'/'\1'/
1504}
1505
1506
1507srpmAutoBuild_rpmbuildCheck() {
1508 # checks that rpm build is installed. If missing asks the user to install it (requires sudo). If they refuse, exit the srpmAutoBuild.
1509
1510 if ! [[ -f /usr/bin/rpmbuild ]]; then
1511 # check that rpmbuild is installed. This isnt checked for by the standard build dependency checks
1512 local userResponse
1513 echo -n -e "\n\nRPMBUILD is required to build SRPMs. Would you like to automatically download and install it from using DNF? \n\n(Y/n) \t "
1514 read userResponse
1515 if [[ ${userResponse,,} =~ ^no?$ ]]; then
1516 echo "rpmbuild will not be downloaded and installed. Exiting srpmAutoBuild."
1517 exit
1518 else
1519 dnf install -y rpmbuild
1520 fi
1521 fi
1522}
1523
1524
1525srpmAutoBuild_rootUserCheck() {
1526 # Checks whether the user who called this function is root. If not, they are prompted to re-run the command as root.
1527
1528 if [[ "${NO_SRPM_AUTO_BUILD_ROOT_CHECK_FLAG}" == "TRUE" ]] || [[ -z "${USER}" ]] || [[ "${USER}" == "root" ]]; then
1529 return
1530
1531 else
1532 local userResponse_RunAsRoot
1533
1534 echo -e "\n\nWARNING: This code is not being run as the root user. (Detected user: ${USER}) \nMany functions will not work properly when run as a user other than root. \n\nWould you like to have the code modify itself to run as root? (timeout = 15 seconds) \n\ny[es]: (DEFAULT) automatically switch to run as root. \nn[o]: continue running as the current user. \nq[uit]: quit srpmAutoBuild \n\nSPECIAL CASE: Respon with 'NO STOP' (case-sensitive) to continue running as the current user AND do not ask again (can be reset by clearing global variable 'NO_SRPM_AUTO_BUILD_ROOT_CHECK_FLAG') \n"
1535 read -ie -p "(Y/n/q): " -t 15 userResponse_RunAsRoot
1536
1537 [[ ${userResponse_RunAsRoot,,} =~ ^q(uit)?$ ]] && exit
1538
1539 [[ "${userResponse_RunAsRoot}" == "NO STOP" ]] && NO_SRPM_AUTO_BUILD_ROOT_CHECK_FLAG=TRUE && export NO_SRPM_AUTO_BUILD_ROOT_CHECK_FLAG && userResponse_RunAsRoot="no"
1540
1541 if ! [[ ${userResponse_RunAsRoot,,} =~ ^no?$ ]]; then
1542
1543 su -p -c "source /root/.bashrc; source /usr/local/bin/my-scripts/srpmAutoBuild.sh; sleep 2; $(echo "$(history 1)" | sed -E s/'^[^0-9]*[0-9]*[^0-9a-zA-Z]*([0-9a-zA-Z].*)$'/'\1'/)" && exit
1544 fi
1545 fi
1546
1547}
1548
1549
1550srpmAutoBuild_setuptree() {
1551 # setup directories used by srpmAutoBuild
1552
1553 [[ -z ${RPM_BUILD_DIR} ]] && srpmAutoBuild_setRpmBuildDir
1554
1555 # ensure standard rpm build tree is setup at ${RPM_BUILD_DIR}
1556 # [[ -f /usr/bin/rpmdev-setuptree ]] && rpmdev-setuptree # this doesnt allow for non-standard build tree locations
1557
1558 RPM_BUILD_DIR="${RPM_BUILD_DIR%/}"
1559 # make directories as long as the direcytory immediately under ${RPM_BUILD_DIR} exists. This prevents making directories in an un-initiated mock environment.
1560 if [[ -d "${RPM_BUILD_DIR%/*}" ]]; then
1561 [[ -d "${RPM_BUILD_DIR}" ]] || mkdir "${RPM_BUILD_DIR}"
1562 [[ -d "${RPM_BUILD_DIR}/SPECS" ]] || mkdir "${RPM_BUILD_DIR}/SPECS"
1563 [[ -d "${RPM_BUILD_DIR}/SRPMS" ]] || mkdir "${RPM_BUILD_DIR}/SRPMS"
1564 [[ -d "${RPM_BUILD_DIR}/RPMS" ]] || mkdir "${RPM_BUILD_DIR}/RPMS"
1565 [[ -d "${RPM_BUILD_DIR}/SOURCES" ]] || mkdir "${RPM_BUILD_DIR}/SOURCES"
1566 [[ -d "${RPM_BUILD_DIR}/BUILD" ]] || mkdir "${RPM_BUILD_DIR}/BUILD"
1567 [[ -d "${RPM_BUILD_DIR}/BUILDROOT" ]] || mkdir "${RPM_BUILD_DIR}/BUILDROOT"
1568 fi
1569
1570 # make sure the user owns the entire rpmbuild tree
1571 #chown -R ${USER}:${USER} "${RPM_BUILD_DIR}"
1572
1573}
1574
1575
1576srpmAutoBuild_getRpmNames() {
1577 # gets list of SRPM/RPM package names from all SRPM/RPM packages in the present working directory, or from the directory or (S)RPM package name given as a function input.
1578 # These names are the raw package names, and do not include the version/distro/arch info that the (s)rpm filenames do.
1579 # Multiple directories / (S)RPMs can be given as input, and you can mix-and-match.
1580 # the output RPM names will strip off version and distro and arch info to return just the raw package names.
1581 #
1582 # show all flags: Use Flag '-i' or '--installed' or '-a' or '-all' to list all installed RPMs. This can be combined with a list of directories / (S)RPM names. This Flag does not need to be the 1st input - Results will be output in the same order they are input in.
1583 # '-a' and '--all' will cause the current directory RPM names to be listed after any function inputs have been processed (which is the behavior without any inputs). '-i' and '--installed' will not do this.
1584 #
1585 # recursive dir search Flag: use Flag '-r' or '--recursive' to make and directories passed to this function get searched recursively. Otherwise, only the top level of the specified directory will be scanned for (S)RPMs
1586
1587 local listCurDirFlag=0
1588 local -a inArray
1589 local inArrayCur=""
1590 local rpmNameList=""
1591 local rpmNameListTemp=""
1592 local recursionFlag=0
1593
1594 (( $# == 0 )) && [[ ${1,,} =~ ^-+r(ecursive)?$ ]] && recursionFlag=$((( $recursionFlag + 1 ))) && shift 1
1595
1596 (( $# == 0 )) && listCurDirFlag=1 || inArray=($(echo ${@}))
1597
1598 if (( $listCurDirFlag == 0 )); then
1599
1600 for inArrayCur in "${inArray[@]}"; do
1601
1602 if [[ ${inArrayCur,,} =~ ^-+a(ll)?$ ]] || [[ ${inArrayCur,,} =~ ^-+i(nstall(ed)?)?$ ]]; then
1603
1604 # gets list of ALL installed RPM package names
1605 rpmNameList="$(echo "${rpmNameList}" && rpm --eval "$(rpm -qia | grep -E '^Name {8}\: ' | sed -E s/'^.*\: *(.*)$'/'\1'/ | sort -u)" | sort -u)"
1606
1607 [[ ${inArrayCur,,} =~ ^-+a(ll)?$ ]] && listCurDirFlag=1
1608
1609 elif [[ -d "${inArrayCur}" ]]; then
1610
1611 # get names packages in directory specified in input
1612 rpmNameListTemp="$(rpm -qip $( (( $recursionFlag > 0 )) && find "${inArrayCur}" -type f -name "*.rpm" || find "${inArrayCur}" -maxdepth 1 -type f -name "*.rpm" ) | grep -E '^Name {8}\: ' | sed -E s/'^.*\: *(.*)$'/'\1'/ | sort -u)"
1613 rpmNameList="$(echo "${rpmNameList}" && echo "${rpmNameListTemp}" | grep -v -E '\%{.+\}' && echo "$(rpm --eval "$(echo "${rpmNameListTemp}" | grep -E '\%{.+\}')")" | sort -u)"
1614
1615 elif [[ "${inArrayCur}" == *".rpm" ]] && [[ -f "${inArrayCur}" ]]; then
1616
1617 # get name of the specific package specified in input
1618 rpmNameList="$(echo "${rpmNameList}" && echo "$(rpm --eval "$(rpm -qip ${inArrayCur} | grep -E '^Name {8}\: ' | sed -E s/'^.*\: *(.*)$'/'\1'/ | sort -u)")" | sort -u)"
1619
1620 elif [[ -n "$(dnf info "$(echo "${inArrayCur%.rpm}" | sed -E s/'(.*)\.((src)|(noarch)|(x86_64)|(i686))$'/'\1'/)" 2>/dev/null)" ]]; then
1621
1622 # get name using `dnf info`
1623 rpmNameList="$(echo "${rpmNameList}" && echo "$(dnf info "$(echo "${inArrayCur%.rpm}" | sed -E s/'(.*)\.((src)|(noarch)|(x86_64)|(i686))$'/'\1'/)" | grep -E '^Name' | sed -E s/'^Name *\: (.*)$'/'\1'/)")"
1624 #echo "${inArrayCur%.rpm}" | sed -E s/'(.*)\.((src)|(noarch)|(x86_64)|(i686))$'/'\1'/
1625
1626 else
1627
1628 echo -e "\n\nWARNING: Input ${inArrayCur} was not found as a directory nor a (S)RPM package name/path. \nIf this is infact a valid path of a directory or (S)RPM package, this likely means you do not have permission to access the said directory or file. \nIn this case, you should either re-run this as a different user with access (e.g., root), or change the owner/permissions using chown/chmod. \n\n"
1629
1630 rpmNameList="$(echo "${rpmNameList}" && echo "UNKNOWN")"
1631
1632 fi
1633
1634 done
1635
1636 fi
1637
1638 if (( $listCurDirFlag == 1 )); then
1639
1640 rpmNameList="$(echo "${rpmNameList}" && echo "$(rpm --eval "$(rpm -qip -- *.rpm | grep -E '^Name {8}\: ' | sed -E s/'^.*\: *(.*)$'/'\1'/ | sort -u)")")"
1641
1642 fi
1643
1644 echo "${rpmNameList}"
1645
1646}
1647
1648
1649
1650srpmAutoBuild_filterByIndex() {
1651 # Filter ${1} by the indices described in ${2}. This uses a "logical indexing" approach.
1652 # Looks for matches where ${2} is equal to the number specified in ${3}.
1653 # If ${#} is missing it looks for matched where ${2} == 1.
1654 # if the 2 arrays arent the same length, the longer one will be truncated to match the length of the shorter one
1655 #
1656 # NOTE: this should be called as: `srpmAutoBuild_filterByIndex "${a[*]}" "${b[*]}" ${c}` ; where ${c} is optional if you want c == 1.
1657
1658 srpmAutoBuild_setRpmBuildDir
1659
1660 local -a arrayToFilter
1661 local -a indList
1662 local nn=0
1663 local numVals=0
1664 local indSelect=1
1665
1666 arrayToFilter=($(echo "${1}"))
1667 indList=($(echo "${2}"))
1668
1669 [[ -n ${3} ]] && [[ ${3} =~ ^[0-9]+$ ]] && indSelect=${3}
1670
1671 if (( ${#indList[@]} <= ${#arrayToFilter[@]} )); then
1672 numVals=${#indList[@]}
1673 (( ${#indList[@]} < ${#arrayToFilter[@]} )) && arrayToFilter=(${arrayToFilter[@]:0:$numVals})
1674 else
1675 numVals=${#arrayToFilter[@]}
1676 indList=(${indList[@]:0:$numVals})
1677 fi
1678 numVals=$((( $numVals - 1 )))
1679
1680 # filter and echo output
1681 # annoyingly, this doesnt work as intended in mock. Mock doesnt seem to support the <(...) notation...
1682 if srpmAutoBuild_isMock; then
1683 # we are in mock, and <(...) doesnt work
1684
1685 echo ${arrayToFilter[@]} | sed -E s/' '/'\n'/g > "${RPM_BUILD_DIR}/.tempList1"
1686 echo ${indList[@]} | sed -E s/' '/'\n'/g > "${RPM_BUILD_DIR}/.tempList2"
1687
1688 echo "$(diff --width=512 -ywd "${RPM_BUILD_DIR}/.tempList1" "${RPM_BUILD_DIR}/.tempList2" | grep -E '\|.*'"${indSelect}" | sed -E s/'^(.*)\|.*$'/'\1'/)"
1689
1690 \rm -rf "${RPM_BUILD_DIR}/.tempList1" "${RPM_BUILD_DIR}/.tempList2"
1691
1692 else
1693 # use better method
1694 echo "$(diff --width=512 -ywd <(echo ${arrayToFilter[@]} | sed -E s/' '/'\n'/g) <(echo ${indList[@]} | sed -E s/' '/'\n'/g) | grep -E '\|.*'"${indSelect}" | sed -E s/'^(.*)\|.*$'/'\1'/)"
1695 fi
1696
1697}
1698
1699
1700
1701srpmAutoBuild_SRPM_download() {
1702 # Download new/updated SRPM packages into ${RPM_BUILD_DIR}/SRPMS for all rpm packages in the current directory (or in directory specified by $2, or in ${RPM_BUILD_DIR}/SRPMS" if $2 is the Flag '--srpm-dir'
1703 # use Flag '--all' to download srpms for ALL installed RPMS and all spec files in ${RPM_BUILD_DIR}/SPECS
1704 # BUT do not download SRPMS for packages that are excluded from being built (listed in ${RPM_BUILD_DIR}/BUILD-EXCLUDE-LIST) OR that were just downloaded as build dependencies (listed in ${RPM_BUILD_DIR}/.srpmAutoBuild-database/installed-build-dependencies)
1705 # To download SRPMS for these excluded packages, rename/delete ${RPM_BUILD_DIR}/BUILD-EXCLUDE-LIST and/or ${RPM_BUILD_DIR}/.srpmAutoBuild-database/installed-build-dependencies and then re-run this function
1706 #
1707 # This initially composes 2 lists:
1708 # 1) list of installed RPM package names and names from current spec files, and
1709 # 2) list of packages excluded from being build and/or that were only downloaded as build dependencies
1710 # Next, *-devel, *-debuginfo and *-debugsource package names are removed (these all come from the base src.rpm package)
1711 # Then, the lists are sorted and have their duplicate entires removed
1712 # Finally, the lists are compared using `diff` and only packages that are present on list (1) but not list (2) have their srpm's downloaded via `dnf download --source`
1713
1714
1715 local downloadDir=""
1716 #local invalidArchList=""
1717 local dirOrig=""
1718 local downloadAllFlag=0
1719
1720 [[ ${1,,} =~ ^-+a(ll)?$ ]] && downloadAllFlag=1 && shift 1
1721
1722 [[ -d ${1} ]] && downloadDir="${1}"
1723 [[ ${1,,} =~ ^-+srpm(-?dir)?$ ]] && downloadDir="${RPM_BUILD_DIR}/SRPMS"
1724 [[ -z "${downloadDir}" ]] && downloadDir="$(pwd)"
1725
1726 echo "Checking DNF for new and updated SRPMs for ALL installed RPM packages"
1727
1728 dirOrig="$(pwd)"
1729
1730 cd "${downloadDir}"
1731
1732 [[ -z $(rpm -qa | grep 'dnf-plugins-core') ]] && dnf install 'dnf-command(builddep)' 'dnf-command(download)'
1733
1734 [[ -n $(find ${dirOrig} -maxdepth 1 -type f -name "*.spec" ; find ${dirOrig} -maxdepth 1 -type f -name "*.rpm") ]] && ( dnf download --source --skip-broken $(find ${dirOrig} -maxdepth 1 -type f -name "*.spec" | sed -E s/'^.*\/([^\/]*)\.spec'/'\1'/) ; dnf download --source --skip-broken ${dirOrig}/*.rpm )
1735
1736 if (( $downloadAllFlag > 0 )); then
1737
1738 if srpmAutoBuild_isMock; then
1739 # we are in mock. No support for <(...)
1740
1741 # avoid re-downloading srpms with invalid archs
1742 #[[ -d "${RPM_BUILD_DIR}/SRPMS/.INVALID_ARCH" ]] && ( invalidArchList="$(find "${RPM_BUILD_DIR}/SRPMS/.INVALID_ARCH" -type f -name "*.rpm")" ; mv -n ${invalidArchList} "${downloadDir}" )
1743
1744 # download sources
1745 dnf download --source --skip-broken $(srpmAutoBuild_getRpmNames -i)
1746
1747 # move srpms with invalid arch's back
1748 #[[ -d "${RPM_BUILD_DIR}/SRPMS/.INVALID_ARCH" ]] && \mv -f $(echo "${invalidArchList}" | sed -E s/'^.*\/\.INVALID_ARCH\/(.*)$'/'\2'/) "${RPM_BUILD_DIR}/SRPMS/.INVALID_ARCH/"
1749
1750 else
1751 # not in mock...use the "better version"
1752
1753 dnf download --source --skip-broken $(diff --width=512 -ywd --suppress-common-lines <(echo "$(srpmAutoBuild_getRpmNames --installed) $(find ${RPM_BUILD_DIR}/SPECS/ -type f -name "*.spec" | sed -E s/'^.*\/([^\/]*)\.spec$'/'\1'/)" | grep -E -v '(-devel|-debuginfo|-debugsource)' | sort -u) <(echo "$(cat ${RPM_BUILD_DIR}/BUILD-EXCLUDE-LIST) $(cat ${RPM_BUILD_DIR}/.srpmAutoBuild-database/installed-build-dependencies)" | grep -E -v '(-devel|-debuginfo|-debugsource)' | sort -u) | grep -E '[\<\|]' | sed -E s/'^([^\<\|]*)[\<\|].*$'/'\1'/)
1754 fi
1755 fi
1756
1757 cd "${dirOrig}"
1758
1759}
1760
1761
1762srpmAutoBuild_build_SRPM_SPEC() {
1763 # build SPECfiles from SRPMs specified as function inputs or (if present) using the list at "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST" or (if no input using the SRPMS
1764 # FLAGS --update-specfile-database and --no-update-specfile-database will force enabling/disabling an on disk database to store some info
1765 # the database is mainly a legacy holdover from a previous version of the code, but the following files are used. They are all in the ${RPM_BUILD_DIR} directory
1766 #
1767 # ${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST: List of SRPMs to build into specs. If empty/missing then will use any srpms in ${RPM_BUILD_DIR}/SRPMS
1768 # ${RPM_BUILD_DIR}/.SRPM-SPEC-BUILt-LIST: List of SRPMS that were sucessfully built into specfiles
1769 # ${RPM_BUILD_DIR}/.SRPM-SPEC-FAILED-LIST: List of SRPMS that were NOT sucessfully built into specfiles, due to a failure during %prep of because the file couldnt be found
1770
1771 # make sure rpmbuild is installed
1772 srpmAutoBuild_setEnvVars
1773
1774 local -a srpmSpecBuildList # SPEC-files that need to be built from SRPMs
1775 local failedPrepFlagCur=0
1776 local updateDatabaseFlag=0
1777 local srpmCur=""
1778 local nn=0
1779 local forceFlag=0
1780 local specsForceRebuildFlag=0
1781 local skipCurFlag=0
1782 local nameMatchCur=""
1783 local forceFlagTempIndicator
1784
1785 if [[ ${1,,} =~ ^-+f(orce)?$ ]]; then
1786 forceFlag=1
1787 specsForceRebuildFlag=1
1788
1789 elif [[ ${1,,} =~ ^-+f(orce)?[0-9]?$ ]]; then
1790 forceFlagTempIndicator="$(echo "${1,,}" | sed -E s/'^[a-z]*([0-9])$'/'\1'/)"
1791 (( $forceFlagTempIndicator > 1 )) && forceFlag=1 && forceFlagTempIndicator=$((( $forceFlagTempIndicator - 2 )))
1792 (( $forceFlagTempIndicator > 1 )) && forceFlagTempIndicator=1
1793 specsForceRebuildFlag=${forceFlagTempIndicator}
1794 fi
1795
1796 # determine if we need to update the database.
1797 # Default when called without specfile inputs is to update unless unless '--no-update-database' is given and is the only input
1798 # Default when called with specfile inputs is to not update unless unless '--update-database' is given as 1st input
1799
1800 if [[ ${1,,} =~ ^-+no-?update(-?spec(file)?(-?data(base)?)?)?$ ]]; then
1801 updateDatabaseFlag=0
1802 shift 1
1803 elif [[ ${1,,} =~ ^-+update(-?spec(file)?(-?data(base)?)?)?$ ]]; then
1804 updateDatabaseFlag=1
1805 shift 1
1806 else
1807 [[ -f "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST" ]] && [[ -n $(cat "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST") ]] && updateDatabaseFlag=1 || updateDatabaseFlag=0
1808 fi
1809
1810 # load list of SRPM-to-build-into-spec-files filenames (if no input) or assign input as SRPM names to build specfiles for
1811
1812 if (( $updateDatabaseFlag == 1 )) && [[ -f "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST" ]]; then
1813
1814 srpmSpecBuildList=($(cat "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST"))
1815
1816 [[ -f "${RPM_BUILD_DIR}/.SRPM-SPEC-FAILED-LIST" ]] && mv -f "${RPM_BUILD_DIR}/.SRPM-SPEC-FAILED-LIST" "${RPM_BUILD_DIR}/.SRPM-SPEC-FAILED-LIST.old"
1817 [[ -f "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILT-LIST" ]] && mv -f "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILT-LIST" "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILT-LIST.old"
1818 touch "${RPM_BUILD_DIR}/.SRPM-SPEC-FAILED-LIST"
1819 touch "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILT-LIST"
1820
1821 elif (( $# > 1 )); then
1822 srpmSpecBuildList=(${@})
1823 else
1824 srpmSpecBuildList=($(find "${RPM_BUILD_DIR}/SRPMS" -maxdepth 1 -type f -name "*.src.rpm"))
1825 fi
1826
1827 (( ${#srpmSpecBuildList[@]} == 0 )) && echo "NO SRPMS TO BUILD! EXITING..." && return
1828
1829 echo -e "\n\nINSTALLING BUILD DEPENDENCIES... \n"
1830 srpmAutoBuild_builddep "${srpmSpecBuildList[@]}"
1831
1832 # Build new specfiles from selected SRPMs
1833
1834 # if building multiple SPECs, list how many
1835 (( ${#srpmSpecBuildList[@]} > 1 )) && echo -e "\n\nNOTICE: ${#srpmSpecBuildList[@]} spec file(s) will now be build from SRPM package(s). \n\n" || echo -e "\n\n" &&
1836
1837 for srpmCur in "${srpmSpecBuildList[@]}"; do
1838
1839 skipCurFlag=0
1840
1841 (( $forceFlag == 0 )) && nameMatchCur="$(srpmAutoBuild_getInfo -n -v -a $(find {"${RPM_BUILD_DIR}/RPMS","${LOCALREPO_DIR}/built"} -type f -name "*$(srpmAutoBuild_getInfo -n "${srpmCur}")*.rpm" | grep -v '/cache/'))" && [[ -n "${nameMatchCur}" ]] && [[ -n "$( echo "${nameMatchCur}" | grep -F "$(srpmAutoBuild_getInfo -n -v -a "${srpmCur}")")" ]] && skipCurFlag=1
1842 (( specsForceRebuildFlag == 0 )) && nameMatchCur="$(srpmAutoBuild_getInfo -n -v -a $(find "${RPM_BUILD_DIR}/SPECS" -type f -name "*$(srpmAutoBuild_getInfo -n "${srpmCur}")*.spec"))" && [[ -n "${nameMatchCur}" ]] && [[ -n "$( echo "${nameMatchCur}" | grep -F "$(srpmAutoBuild_getInfo -n -v -a "${srpmCur}")")" ]] && skipCurFlag=1
1843
1844 if (( $skipCurFlag == 0 )); then
1845
1846 echo "A SPEC-file will now be built from: ${srpmCur}"
1847
1848 # Build SPEC-file from SRPM using %{prep}
1849 failedPrepFlagCur=0
1850 [[ -f "${srpmCur}" ]] && rpmbuild -rp "${srpmCur}" || dnf builddep --skip-broken $(srpmAutoBuild_getRpmNames "${srpmCur}") "${srpmCur}" && rpmbuild -rp "${srpmCur}" || rpmbuild -rp "${srpmCur}" --nodeps || failedPrepFlagCur=1
1851
1852 (( $updateDatabaseFlag == 1 )) && (( $failedPrepFlagCur == 0 )) && echo "${srpmCur}" >> "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILT-LIST"
1853 (( $updateDatabaseFlag == 1 )) && (( $failedPrepFlagCur == 1 )) && echo "${srpmCur}" >> "${RPM_BUILD_DIR}/.SRPM-SPEC-FAILED-LIST"
1854
1855
1856 (( $failedPrepFlagCur == 1 )) && echo -e "\nNOTICE: FAILED TO BUILD SPEC: ${nn} \n\n${nn} was not successfully built into a spec-file, either due to a failure during the execution of %{prep}, or because the input file was not found. \n"
1857
1858 # if successful build of SPECfile: copy source into ${RPM_BUILD_DIR}/SRPMS if it isnt already there, and check the name/version of the generated specfile against the SRPM
1859 if (( $failedPrepFlagCur == 0 )); then
1860
1861 # copy SRPM into rpm build tree SRPMS folder
1862 [[ -n "$(find "${RPM_BUILD_DIR}/SRPMS/" -maxdepth 1 -type f -wholename "$(realpath "${srpmCur}")")" ]] || \cp -f "${srpmCur}" "${RPM_BUILD_DIR}/SRPMS/"
1863
1864 # print status/info to screen
1865 echo -e "\nA SPEC-file was successfully generated from ${srpmCur} \n\nThe code will now automatically confirm that it includes valid/parsable name and version information. \nThis ensures that checks made during the build process to avoid re-building already-build specfiles will return valid results. \n"
1866
1867 # Check Name and Version in specfile. If we cant read/parse some info (in particular version info), hard code it using a static expression (no variable anything) based on the SRPM file's info
1868 srpmAutoBuild_check_SpecSrpm_NameVersion "$(srpmAutoBuild_getRpmNames "${srpmCur}").spec" "${srpmCur}"
1869
1870 fi
1871
1872 else
1873
1874 echo -e "\nAn matching and already-build specfile or rpm ppackage was found for ${srpmCur}, and as such it will not be re-buiult into a specfile. \nUse the '-f' or '--force' flags to override this behavior if it is in error. \n"
1875
1876 fi
1877
1878 done
1879
1880}
1881
1882
1883srpmAutoBuild_builddep() {
1884 # download and install build dependencies for the SRPMS we want to build
1885 # Note: this existsw because `dnf builddep` doesnt work with multiple srpms in the same function call, and since dnf is usually slow to initiate a new connection it is VERY slow to call for each SROm individually. This function uses a vectorized approach that is much faster because it extracts all the requiired dependencies for ALL packagges being built using `rpm` , and then maked a single call to dnf to insttal them all. dnf builddep is still used as a backup in the final build script, in case this approach missed (or couldnt parse) a dependent package that dnf builddep identified.
1886 srpmAutoBuild_rootUserCheck
1887
1888
1889 local srpmBuildList=""
1890 local specBuildList=""
1891 local builddepPkgList=""
1892 local recursionFlag=0
1893
1894 [[ ${1,,} =~ ^-+r(ec(ursion)?)? ]] && recursionFlag=1 && shift 1
1895
1896
1897 # get package names from inputs or, if no inputs, from the SRPMS/SPECS present in the default rpm build tree directories
1898
1899 if (( $# == 0)); then
1900 # no inputs - get packages from SRPMS and SPECS folders, unless "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST" exists and is not empty
1901
1902 if [[ -f "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST" ]] && [[ -n "$(cat "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST")" ]]; then
1903 srpmBuildList="$(cat "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST" | grep -E '.src.rpm')"
1904 specBuildList="$(cat "${RPM_BUILD_DIR}/.SRPM-SPEC-BUILD-LIST" | grep -E '.spec')"
1905 else
1906 srpmBuildList="$(find "${RPM_BUILD_DIR}/SRPMS" $( (( $recursionFlag == 0 )) && echo '-maxdepth 1') -type f -name "*.src.rpm")"
1907 specBuildList="$(find "${RPM_BUILD_DIR}/SPECS" -maxdepth 1 -type f -name "*.spec")"
1908 fi
1909
1910 else
1911 # get packages from function input
1912
1913 srpmBuildList="$(echo "${@}" | sed -zE s/' '/'\n'/g | grep -E '\.src\.rpm[ \t]*$')"
1914 specBuildList="$(echo "${@}" | sed -zE s/' '/'\n'/g | grep -E '\.spec[ \t]*$')"
1915 fi
1916
1917 # get build requirements
1918 builddepPkgList="$(echo "$([[ -n "${srpmBuildList}" ]] && echo "$(rpm -qpR $(echo ${srpmBuildList} | sed -zE s/' '/'\n'/g | grep -E '.src.rpm') | sed -E s/'^(.+)$'/'"\1"'/)" || echo ""; [[ -n "${specBuildList}" ]] && echo "$(cat $(echo ${specBuildList} | sed -zE s/' '/'\n'/g | grep -E '.spec') | grep -E '^(Build)?Requires' | sed -E s/'^[^\:]*\:[ \t]*(.*)$'/'"\1"'/)" || echo "")" | sort -u)"
1919
1920 # try and parse things that didnt originally parse using rpm --eval
1921 builddepPkgList="$(echo "$(echo "${builddepPkgList}" | grep -v -E s/'\%\{.*\}')"; [[ -n $(echo "${builddepPkgList}" | grep -E s/'\%\{.*\}') ]] && echo "$(rpm --eval $(echo "${builddepPkgList}" | grep -E s/'\%\{.*\}'))" | sort -u)"
1922
1923 eval 'dnf install --skip-broken -y '$(echo "${builddepPkgList}")
1924
1925}
1926
1927srpmAutoBuild_getInfo() {
1928 # gets info about the name/version of SPEC-files and RPMs and SRPMs
1929 #
1930 # By default, if no (valid) flags,. you will get a human-readable ()
1931 #
1932 # Use the following flags to instead output a (partial) package name, made up of some compination name/ver/arch
1933 # Output will be constructed using standard RPM naming. Using all 3 flags ('-n -v -a') gives $(name)-$(ver).$(arch)
1934 # '-n' or '--name': include name
1935 # '-v' or '--ver(sion)?': include version
1936 # '-a' or '--arch(itecture)?': include arch
1937 #
1938 # NOTE: for RPMS and SRPMs, the arch returned is what is coded into the [S]RPM.
1939 # The specfiles dont seem to *always* include this, so for specfiles the
1940 # arch returned is the current system architecture (i.e., "$(uname -m)"")
1941
1942 local nn=""
1943 local flagsAll=""
1944
1945 [[ "${*,,}" =~ ^(.+ )?-+n(ames?)?( .+)?$ ]] && flagsAll="${flagsAll} -n"
1946 [[ "${*,,}" =~ ^(.+ )?-+v(er(sions?)?)?( .+)?$ ]] && flagsAll="${flagsAll} -v"
1947 [[ "${*,,}" =~ ^(.+ )?-+a(rch(itecture)?)?( .+)?$ ]] && flagsAll="${flagsAll} -a"
1948 #[[ -z "${flagsAll}" ]] && flagsAll="-n -v -a"
1949 [[ -n "${flagsAll}" ]] && flagsAll="$(echo "${flagsAll}" | sed -E s/' *(.*[^( *$)]) *$'/'\1'/)"
1950
1951 for nn in ${@}; do
1952 if [[ ! ${nn} =~ ^-+((n(ames?)?)|(v(er(sions?)?)?)|(a(rch(itecture)?)?))$ ]]; then
1953 if [[ -d "${nn}" ]]; then
1954 [[ -n "$(find "${nn}" -maxdepth 1 -type f -name "*.spec")" ]] && srpmAutoBuild_getInfo_fromSPECs ${flagsAll} "${nn}"
1955 [[ -n "$(find "${nn}" -maxdepth 1 -type f -name "*.rpm")" ]] && srpmAutoBuild_getInfo_fromRPMs ${flagsAll} "${nn}"
1956 else
1957 #[[ -z "${flagsAll}" ]] && echo -e "\nchecking \"${nn}\""
1958 if [[ ${nn} == *.spec ]]; then
1959 srpmAutoBuild_getInfo_fromSPECs ${flagsAll} "${nn}"
1960
1961 elif [[ ${nn} == *.rpm ]]; then
1962 srpmAutoBuild_getInfo_fromRPMs ${flagsAll} "${nn}"
1963
1964 elif [[ ${nn} == ${RPM_BUILD_DIR}/SPECS/* ]]; then
1965 srpmAutoBuild_getInfo_fromSPECs ${flagsAll} "${nn}"
1966
1967 elif ( [[ ${nn} == ${RPM_BUILD_DIR}/SRPMS/* ]] || [[ ${nn} == ${RPM_BUILD_DIR}/RPMS/* ]] || [[ ${nn} == ${LOCALREPO_DIR}/built/* ]] || [[ ${nn} == ${LOCALREPO_DIR}/downloaded/* ]] || [[ ${nn} == ${LOCALREPO_DIR}/source/* ]] ); then
1968 srpmAutoBuild_getInfo_fromRPMs ${flagsAll} "${nn}"
1969 fi
1970 fi
1971 fi
1972 done
1973}
1974
1975srpmAutoBuild_getInfo_fromSPECs() {
1976 # this will isolate the main package name, version, and release in the spec-file and print it.
1977 # It is sort of like an `rpm -qiP` except that it works with spec-files and (optionally) filters the output for name/version info
1978 #
1979 # FLAGS
1980 # '-n' or '--name' --> output package name only
1981 # '-v' or '--ver[sion]' --> output package version + release only, in the form {version}-{release}
1982 # if both of the above flags are present, it will output just the package name + version + release in the form '{name}-{version}-{release}'. This format matches standard RPM file naming protocol.
1983 # if neither of the above flags are present, it will output the full unfiltered info header. This is good for information viewing, but not fdor scripting package names/versions
1984
1985 local nn=""
1986 local kk=0
1987 local specInfoCur=""
1988 local outType=0
1989 local tempCur=""
1990 local -a inAll
1991 local -a inAllTemp
1992 local archFlag=0
1993
1994 [[ "${*,,}" =~ ^(.+ )?-+n(ames?)?( .+)?$ ]] && outType=1
1995 [[ "${*,,}" =~ ^(.+ )?-+v(er(sions?)?)?( .+)?$ ]] && outType=$((( $outType + 2 )))
1996 [[ "${*,,}" =~ ^(.+ )?-+a(rch(itecture)?)?( .+)?$ ]] && archFlag=1
1997
1998 for nn in "$@"; do
1999 # case 1: input is a file
2000 [[ -f "${nn}" ]] && [[ ${nn} == *.spec ]] && inAll[$kk]="${nn}" && ((kk++))
2001
2002 # case 2: input is a directory. scan its top level for specfiles
2003 if [[ -d "${nn}" ]]; then
2004 inAllTemp=($(find "${nn}" -maxdepth 1 -type f -name "*.spec"))
2005 for tempCur in "${inAllTemp[@]}"; do
2006 inAll[$kk]="${tempCur}" && ((kk++))
2007 done
2008 fi
2009 done
2010
2011 for nn in "${inAll[@]}"; do
2012
2013 (( $outType == 0 )) && echo -e "\nSPEC FILE NAME: $nn"
2014
2015 specInfoCur="$(rpm --eval "$(echo -n "$(echo -e "\n\n"; cat "$nn")" | grep -E '^((Name)|(Version)|(Release)|(Summary)|(Epoch)|(License)|(URL))\:|^[ \t]*$' | sed -zE s/'^.*(((\n([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Name\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Version\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Release\:[^\n]*\n))([^\n]*[a-zA-Z0-9]+[^\n]*\n)*)|((\n([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Name\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Release\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Version\:[^\n]*\n))([^\n]*[a-zA-Z0-9]+[^\n]*\n)*)|((\n([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Version\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Name\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Release\:[^\n]*\n))([^\n]*[a-zA-Z0-9]+[^\n]*\n)*)|((\n([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Version\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Release\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Name\:[^\n]*\n))([^\n]*[a-zA-Z0-9]+[^\n]*\n)*)|((\n([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Release\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Version\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Name\:[^\n]*\n))([^\n]*[a-zA-Z0-9]+[^\n]*\n)*)|((\n([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Release\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Name\:[^\n]*\n))(([^\n]*[a-zA-Z0-9]+[^\n]*\n)*(Version\:[^\n]*\n))([^\n]*[a-zA-Z0-9]+[^\n]*\n)*)).*$'/'\1'/ | sed -zE s/'\n*(.*[^\n])\n*$'/'\1\n\n'/)";)"
2016
2017 (( $outType == 0 )) && echo "$(echo "${specInfoCur}"; echo "Architecture: $(uname -m) (build system)")"
2018
2019 (( $outType == 1 )) && echo -n "${specInfoCur}" | grep -E '^Name\:' | sed -E s/'^Name\:[ \t]*([^\n]*\n?)$'/'\1'/ | sed -zE s/'(.*)\n$'/'\1'/
2020
2021 (( $outType == 2 )) && echo -n "$(echo "${specInfoCur}" | grep -E '^Version\:'; echo "${specInfoCur}" | grep -E '^Release\:')" | sed -zE s/'^Version\:[ \t]*([^\n]*)\nRelease\:[ \t]*([^\n]*\n?)$'/'\1-\2'/
2022
2023 (( $outType == 3 )) && echo -n "$(echo "${specInfoCur}" | grep -E '^Name\:'; echo "${specInfoCur}" | grep -E '^Version\:'; echo "${specInfoCur}" | grep -E '^Release\:')" | sed -zE s/'^Name\:[ \t]*([^\n]*)\nVersion\:[ \t]*([^\n]*)\nRelease\:[ \t]*([^\n]*\n?)$'/'\1-\2-\3'/
2024
2025 (( $archFlag == 1 )) && echo ".$(uname -m)" || echo ""
2026
2027 (( $outType == 0 )) && echo -e "----------------------------------------------------------------------\n"
2028
2029 done
2030
2031}
2032
2033srpmAutoBuild_getInfo_fromRPMs() {
2034 # this will isolate the main package name, version, and release in the srpmfile and print it.
2035 # This calls `rpm -qiP` and (optionally) filters the output for name/version info --> works with rpoms and srpms
2036 #
2037 # FLAGS
2038 # '-n' or '--name' --> output package name only
2039 # '-v' or '--ver[sion]' --> output package version + release only, in the form {version}-{release}
2040 # '-a' or '--arch[itecture]' --> output package intended architecture
2041 # if more than 1 of the above flags are present, it will output the listed flags in the following order (unlisted flags will haver the corresponding info omitted): '{name}-{version}-{release}.{arch}'. This format matches standard RPM file naming protocol.
2042 # if neither of the above flags are present, it will output the full unfiltered info header. This is good for information viewing, but not fdor scripting package names/versions
2043
2044 local nn=""
2045 local kk=0
2046 local srpmInfoCur=""
2047 local nameCur=""
2048 local verCur=""
2049 local archCur=""
2050 local outNameFlag=0
2051 local outVerFlag=0
2052 local outArchFlag=0
2053 local outType=1
2054 local -a inAll
2055
2056 [[ "${*,,}" =~ ^(.+ )?-+n(ames?)?( .+)?$ ]] && outNameFlag=1
2057 [[ "${*,,}" =~ ^(.+ )?-+v(er(sions?)?)?( .+)?$ ]] && outVerFlag=1
2058 [[ "${*,,}" =~ ^(.+ )?-+a(rch(itecture)?)?( .+)?$ ]] && outArchFlag=1
2059
2060 (( $outNameFlag == 0 )) && (( $outVerFlag == 0 )) && (( $outArchFlag == 0 )) && outType=0
2061
2062 for nn in "$@"; do
2063 # case 1: input is a file
2064 [[ -f "${nn}" ]] && [[ ${nn} =~ ^.*(\.src)?\.rpm$ ]] && inAll[$kk]="${nn}" && ((kk++))
2065
2066 # case 2: input is a directory. scan its top level for [s]rpms
2067 if [[ -d "${nn}" ]]; then
2068 inAllTemp=($(find "${nn}" -maxdepth 1 -type f -name "*.rpm"))
2069 for tempCur in "${inAllTemp[@]}"; do
2070 inAll[$kk]="${tempCur}" && ((kk++))
2071 done
2072 fi
2073 done
2074
2075 for nn in "${inAll[@]}"; do
2076
2077 (( $outType == 0 )) && echo -e "\nSRPM NAME: $nn"
2078
2079 srpmInfoCur="$(rpm --eval "$(rpm -qip "${nn}")")"
2080
2081 if (( $outType == 0 )); then
2082
2083 echo "${srpmInfoCur}"
2084 echo -e "\n--------------------------------------------------------\n"
2085
2086 else
2087
2088 (( $outNameFlag == 1 )) && nameCur="$(echo "${srpmInfoCur}" | grep -E '^Name {8}:' | sed -E s/'^.*\:[ \t]*(.*)$'/'\1'/)" || nameCur=""
2089
2090 (( $outVerFlag == 1 )) && verCur="$([[ -z "${nameCur}" ]] || echo '-')$(echo "$(echo "${srpmInfoCur}" | grep -E '^Version {5}\:'; echo "${srpmInfoCur}" | grep -E '^Release[ \t]+\:')" | sed -z -E s/'^Version {5}\:[ \t]*([^\n]*)\nRelease {5}\: *([^\n]*\n?)$'/'\1-\2\n'/g)" || verCur=""
2091
2092 (( $outArchFlag == 1)) && archCur="$([[ -z "${nameCur}${verCur}" ]] || echo '.')$(echo "${srpmInfoCur}" | grep -E '^Architecture\:' | sed -E s/'^Architecture\:[ \t]*(.*)$'/'\1'/)" || archCur=""
2093
2094 echo "${nameCur}${verCur}${archCur}"
2095
2096 fi
2097
2098 done
2099
2100}
2101
2102
2103srpmAutoBuild_check_SpecSrpm_NameVersion() {
2104 # compares the version of a specfile ($1) and srpm ($2). Inputs should use full file paths.
2105 # If the names are the same and the specfile version is invalid, it will be overwritten with the version of the srpm.
2106 # the utility in this is in avoiding re-building RPM's you have already built. The code will attempt to match up SPEC files to already build RPMs, but will only skip building if there is a perfect name and package match. This sort of match requires the name and version to parse correctly.This usually is the case for SRPM's, but often times the SPEC files use dynamic variable-based names that `rpm` doesnt seem to be able to parse outside of actually building the package, meaning the code wont find a matching RPM unless the dynamic variable names are replaced with static names derived from the SRPM.
2107
2108 #local infoSPEC=""
2109 local nameSPEC=""
2110 local verSPEC=""
2111 local nameSRPM=""
2112 local verSRPM=""
2113 local nameRep=""
2114
2115 # extract names and versions from the SPEC-file and SRPM
2116
2117 # SPEC Info
2118
2119 # get name and version from srpm using `rpm --eval` and the specfile contents. Filter specfile contents to find a grouping with at least 3 of the following fields: Name, Version, Release, Summary. Some specfiles have >1 lines beginning with "Name", but should only contain 1 group like this, and the "Name" field from this group is the one we want.
2120
2121 #infoSPEC="$( cat "${1}" | grep -z -o -P '(\n((Name)|(Version)|(Release)|(Summary))\:[^(\n)]*){3,4}' | sed -E s/'[ \t]+'/' '/g | sed -E s/'^Summary.*$'// | sed -z -E s/'\n+'/'\n'/g | sed -z -E s/'\nRelease\:[ \t]*'/'-'/g)"
2122
2123 #infoSPEC="$(srpmAutoBuild_getInfo_fromSPECs "${1}")"
2124 #nameSPEC="$(rpm --eval "$(echo "${infoSPEC}" | grep -E '^Name\:' | sed -E s/'^Name\:[ \t]*(.*)$'/'\1'/)")"
2125
2126 #erSPEC="$(rpm --eval "$(echo "${infoSPEC}" | grep -E '^Version\:' | sed -E s/'^Version\:[ \t]*(.*)$'/'\1'/)")"
2127
2128 nameSPEC="$(srpmAutoBuild_getInfo_fromSPECs -n "${1}")"
2129 verSPEC="$(srpmAutoBuild_getInfo_fromSPECs -v "${1}")"
2130
2131 # secondary check in case the 1st didnt work. dont filter the specfile, just grab the 1st line starting with Name/Version and use that
2132
2133 [[ -z "${nameSPEC}" ]] && nameSPEC="$(rpm --eval "$(cat "${1}" | grep -E '^Name\:' | head -n 1 | sed -E s/'^.*\:[ \t]*(.*)$'/'\1'/)")"
2134 [[ -z "${nameSPEC}" ]] && nameSPEC="${1%.spec}"
2135
2136 [[ -z "${verSPEC}" ]] && verSPEC="$(rpm --eval "$(cat "${1}" | grep -E '^Version\:' | head -n 1 | sed -E s/'^.*\:[ \t]*(.*)$'/'\1'/)")"
2137
2138 # SRPM Info
2139
2140 # get name and version from srpm using `rpm --eval` and `rpm --qip`
2141
2142 #nameSRPM="$(rpm --eval "$(rpm -qip "${2}" | grep -E '^Name {8}\:' | sed -E s/'^.*\: *(.*)$'/'\1'/)")"
2143 #verSRPM="$(rpm --eval "$(rpm -qip "${2}" | grep -E '^Version {5}\:|^Release {5}\:' | sed -z -E s/'Version[^\:]*\: *([^\n]*)\nRelease[^\:]*\: *([^\n]*)\n'/'\1-\2\n'/g)")"
2144
2145 nameSRPM="$(srpmAutoBuild_getInfo_fromRPMs -n "${2}")"
2146 verSRPM="$(srpmAutoBuild_getInfo_fromRPMs -v "${2}")"
2147
2148 # secondary check in case the 1st didnt work. Get name and/or version direct from the srpm name, not its contents.
2149
2150 [[ -z "${nameSRPM}" ]] && nameSRPM="$(echo "${2##*/}" | sed -E s/'^(.*)-[^-]*-[^\.]*\.[^\.]*\.src\.rpm'/'\1'/)"
2151
2152 [[ -z "${verSRPM}" ]] && verSRPM="$(echo "${2##*/}" | sed -E s/'^.*-([^-]*-[^\.])*\.[^\.]*\.src\.rpm'/'\1'/)"
2153
2154 # fix "Name" in the SPEC file (if needed)
2155
2156 if [[ "${nameSPEC}" != "${nameSRPM}" ]]; then
2157
2158 # determine replacement package name
2159 if [[ ${2} == *"${1%%.spec}"* ]]; then
2160 # use name from specfile filename, since this matches the start of the srpm filename
2161 nameRep="${1%%.spec}"
2162 else
2163 # use name derived from the srpm package
2164 nameRep="${nameSRPM}"
2165 fi
2166
2167 # add name to spec-file
2168 if [[ -n "$(cat ${1} | grep -E '^Name\: ')" ]]; then
2169 # name field exists. overwrite name. In case multiple lines begin with "Name: ", overwrite the 1st one only
2170 sed -z -i -E s/'\nName\: [^\n]*'/'\nName\: '"$(srpmAutoBuild_escapeRegexChars "${nameRep}")"''/
2171 else
2172 # Add "Name: ____" entry to the start (1st line) of spec file
2173 echo "$(echo "Name: ${nameRep}" && cat "${1}")" > "${1}"
2174 fi
2175
2176 fi
2177
2178 # fix "Version" in the SPEC file (if needed)
2179
2180 if [[ -z "${verSPEC}" ]] || ( [[ "${verSPEC}" != "${verSRPM}" ]] && [[ "${2}" != *"${verSPEC}"* ]] && [[ ${verSRPM} =~ ^.+$ ]] ); then
2181
2182 if [[ -n "$(cat ${1} | grep -E '^Name\:')" ]]; then
2183 # name field exists. overwrite name.
2184 sed -i -E s/'^Version {5}\:.*$'/'Version \: '"$(srpmAutoBuild_escapeRegexChars "${verSRPM}")"''/
2185 else
2186 echo "$(echo "$(cat ${1} | grep -E '^Name {8}\:')" && echo "Version : ${verSRPM}" && echo "$(cat "${1}" | grep -v -E '^Name {8}\:')")" > "${1}"
2187 fi
2188
2189 fi
2190
2191}
2192
2193
2194srpmAutoBuild_escapeRegexChars() {
2195 # escape regex characters.
2196 #
2197 # flag: --newline-mod or '-n' --> transform leading newlines into '(^|\n)' and trailing newlines into '(\n|$)' (instead of just '\n')
2198 # flag: --glob-mod or '-g' --> transform '*' into '.*' (instead of '\*')
2199 #
2200 # Intended usage: running `sed [-iz] -E s/"$(srpmAutoBuild_escapeRegexChars "$stringToReplace")"/'<replacementString>'/[g]`.
2201 # This should make `sed -E` match whatever the literal (un-escaped) text in `$stringToReplace` is
2202
2203 local strMod=""
2204 local newlineModFlag=0
2205 local globModFlag=0
2206
2207 (( $# == 0 )) && echo -n "" && return
2208 strMod="${*}"
2209
2210 [[ ${strMod,,} =~ ^(.+ )?-+n((ewline)?(-?m(od)?)?)( .+)?$ ]] && newlineModFlag=1 && strMod="$(echo "${strMod}" | sed -zE s/'^-+[Nn](([Ee][Ww][Ll][Ii][Nn][[Ee])?(-?[Mm][Oo][Dd])?)? ?'//g | sed -zE s/'-+[Nn](([Ee][Ww][Ll][Ii][Nn][[Ee])?(-?[Mm][Oo][Dd])?)? ?'/' '/g)"
2211 [[ ${strMod,,} =~ ^(.+ )?-+g((lob)?(-?m(od)?)?)( .+)?$ ]] && globModFlag=1 && strMod="$(echo "${strMod}" | sed -zE s/'^-+[Gg](([Ll][Oo][[Bb])?(-?[Mm][Oo][Dd])?)? ?'//g | sed -zE s/'-+[Gg](([Ll][Oo][[Bb])?(-?[Mm][Oo][Dd])?)? ?'/' '/g)"
2212
2213
2214 strMod="${strMod//\\/\\\\}"
2215 strMod="${strMod//./\\.}"
2216 strMod="${strMod//\//\\\/}"
2217 strMod="${strMod//\(/\\\(}"
2218 strMod="${strMod//\)/\\\)}"
2219 strMod="${strMod//\[/\\\[}"
2220 strMod="${strMod//\{/\\\{}"
2221 strMod="${strMod//\?/\\\?}"
2222 strMod="${strMod//\+/\\\+}"
2223 strMod="${strMod//\|/\\\|}"
2224 strMod="${strMod//\^/\\\^}"
2225 strMod="${strMod//\$/\\\$}"
2226 strMod="${strMod//\!/\\\!}"
2227 strMod="${strMod//"'"/"'\"'\"'"}"
2228 (( $globModFlag == 1 )) && strMod="${strMod//\*/.\*}" || strMod="${strMod//\*/\\\*}"
2229 strMod="$(echo -n "${strMod}" | sed -zE s/'\t'/'\\t'/g | sed -zE s/'\n'/'\\n'/g)"
2230 (( $newlineModFlag == 1 )) && strMod="$(echo -n "${strMod}" | sed -zE s/'^\\n'/'\(\^\|\\n\)'/ | sed -zE s/'\\n$'/'\(\\n\|\$\)'/)"
2231
2232 echo -n "${strMod}"
2233}
2234
2235
2236srpmAutoBuild_getUniqueDir() {
2237 # Appends a directory name given as function input by increasingly larger numbers until it finds a directory name that doesnt exist
2238 # Default behavior it to create the unique directory as a new, empty directory
2239 # Use flag '-n' or --no-make' or '--no-create' to not make the directory and just return the name instead
2240
2241 local noMakeFlag=0
2242 local uniqueDirName=""
2243
2244 [[ ${1,,} =~ ^-+no?-?((m(ake)?)|(c(reate)?))?$ ]] && noMakeFlag=1 && shift 1
2245
2246 uniqueDirName="$(srpmAutoBuild_getUniqueName -n "${*}")"
2247
2248 (( $noMakeFlag == 0 )) && mkdir --parents "${uniqueDirName}"
2249
2250 echo -n "${uniqueDirName}"
2251}
2252
2253
2254srpmAutoBuild_getUniqueName() {
2255 # appends a name by increasingly larger numbers until it finds a name that doesnt exist (as any object type) in the filesystem
2256 # NOTE: inputs are combined via "${*}" --> multiple inputs are treated as [single] spaces in the object name
2257 # NOTE: order of checking is "${*}", "${*}0", "${*}1", etc.
2258 # This behavior means that if the input ends with '/' it will check if the input exists, then checks for subdirectories under "${*}" that are named "0", "1", etc.
2259 # If "${*}" ends in a '/' and exists but NOT as a directory, the ending '/' will be removed and the result will be a unique directory name "${*}[#]"
2260 #
2261 # Default behavior is to use a trailing newline unless the 1st input is the flag '-n' or '---no-newline'. This is to match the behavior of 'echo <...>' and 'echo -n <...>'.
2262
2263 local nf=""
2264 local uniqueName=""
2265
2266 [[ ${1} =~ ^-+n(o-?newline)?$ ]] && nf='-n' && shift 1
2267 uniqueName="${*}"
2268
2269 [[ -z "${uniqueName}" ]] && echo "WARNING: no input. Returning <null>." >&2 && echo ${nf} "" && return
2270
2271 if [[ -e ${uniqueName} ]]; then
2272 [[ "${uniqueName}" == */ ]] && [[ ! -d "${uniqueName}" ]] && uniqueName="${uniqueName%/}"
2273
2274 local nn=0
2275 while [[ -e "${uniqueName}${nn}" ]]; do
2276 ((nn++))
2277 done
2278
2279 uniqueName="${uniqueName}${nn}"
2280 fi
2281
2282 echo ${nf} "${uniqueName}"
2283}
2284
2285
2286
2287srpmAutoBuild_fixSpecFile_missingDebugSourceFileList() {
2288 # This fixes the common "Build failed because debugsource file cannot be found" error
2289
2290 \cp -f "${*}" "${*}.old"
2291 sed -i -E s/'^\%global debug_package \%\{nil\}.*\n?$\n?'// "${*}"
2292 sed -i -E s/'^\%prep$'/'%global debug_package %{nil}\n\n%prep'/ "${*}"
2293}
2294
2295
2296srpmAutoBuild_switchSpecFile() {
2297 # switches between the original and modified spec file. (one of them is *.spec, the other is *.spec.old)
2298
2299 \mv -f "${*}" "${*}.old.temp"
2300 \mv -f "${*}.old" "${*}"
2301 \mv -f "${*}.old.temp" "${*}.old"
2302}
2303
2304
2305srpmAutoBuild_printBuildStats() {
2306 # displays current build progress and some rough statistics about successful / failed / skipped builds
2307 # INPUTS: srpmAutoBuild_printBuildStats "${nn}" "${nFailsCur}" "${kk}" "${ff}" "${ss}" "${nSPECS}"
2308
2309 local numSpecsFinished=0
2310
2311 echo -e "\nBUILD ID# $((( $1 + 1 ))): $( (( ${14} == 1 )) && echo -n "PRIMARY" || echo -n "SECONDARY" ) BUILD PROCESS \n"
2312
2313 if [[ ! ${2} =~ ^NaN[1-3]$ ]]; then
2314
2315 if (( ${2} > 3 )); then
2316
2317 echo -e "\nSTATUS: FAILED! <=========================================================== \n"
2318 else
2319
2320 echo -e "\nSTATUS: BUILT SUCCESSFULLY! ( BUILD ATTEMPT # $((( ${2} + 1 ))) ) \n----> Number of failed initial build attempt(s): ${2} \n"
2321 fi
2322 else
2323 echo -ne "\nSTATUS: SKIPPED! \nREASON: "
2324 (( ${13} == 3)) && echo -n "This specfile is currently being built by the other build process."
2325 (( ${13} == 2 )) && echo -n "A matching RPM with the same package name and version was found in ${RPM_BUILD_DIR}/RPMS, suggesting that this SPEC file has already been built. \n\nNOTE: To ignore matching already built RPMS and force (re)building, use 'srpmAutoBuild_buildSA --force'. Note that this will overwrite the existing RPM, should it exist in ${RPM_BUILD_DIR}/RPMS."
2326 (( ${13} == 1 )) && echo -n "The input SPEC-file could not be located (and/or read, if insufficient permissions)."
2327 [[ ! ${13} =~ ^[1-3]$ ]] && echo -n "UNKNOWN. INDICATOR VARIABLE 'skipCurFlag' HAS TAKEN AN UNSUPPORTED VALUE"
2328 echo -e "\n"
2329 fi
2330
2331 [[ ! -e "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" ]] && (( ${14} == 2 )) && numSpecsFinished=$((( ${6} - ${1} ))) || numSpecsFinished=${1}
2332
2333 echo -e "BREAKDOWN OF BUILDS (BUILD RUN: $( (( ${14} == 1 )) && echo "primary" || echo "secondary")) \n"
2334
2335 echo -e "OVERALL BUILD STATS (This Build Run Only): ${3} Successes | ${4} Failures | ${5} Skipped/Excluded \n"
2336 echo -e "CURRENT OVERALL PROGRESS (All Build Runs): ${numSpecsFinished} of ${6} SPEC-files Processed ----> $((( ( $numSpecsFinished * 100 ) / ${6} )))% Complete\n"
2337
2338 echo -e "BREAKDOWN OF INDIVIDUAL BUILD ATTEMPTS \n\nSuccess on First Attempt: \t\t ${7} \n1 Failure then Success: \t\t ${8}\n2 Failures then Success: \t\t ${9} \n3 Failures then Success: \t\t ${10} \nFailed All 4 Build Attempts: \t ${11} \nBuild was Skipped: \t\t ${12} \n"
2339}
2340
2341
2342srpmAutoBuild_checkBuildStatus() {
2343 # FLAGS:
2344 # '-s' or '--simple' gives number of SPECS done.
2345 # '-a' or '--all' prints the entire detailed status record.
2346 # '-sbs' or '--side-by-side' gives the same output as '-all' but placed in 2 columns using 'diff'
2347 # Optional: use '-sbs=<#>' or '--side=-by-side=<#>' to specify the combined width of both columns.
2348 # Default width is 200. Less than ~190 will start to cut off info from the 2 columns.
2349 # Default is print the detailed status record but from the most recent build only.
2350
2351 local isPresentFlag=0
2352 [[ -f "${RPM_BUILD_DIR}/.STATUS_1" ]] && [[ -n $(cat "${RPM_BUILD_DIR}/.STATUS_1") ]] && isPresentFlag=$((( $isPresentFlag + 1 )))
2353 [[ -f "${RPM_BUILD_DIR}/.STATUS_2" ]] && [[ -n $(cat "${RPM_BUILD_DIR}/.STATUS_2") ]] && isPresentFlag=$((( $isPresentFlag + 2 )))
2354
2355 if (( $# > 0 )) && [[ ${1,,} =~ ^-+a(ll)? ]]; then
2356
2357 (( $isPresentFlag == 3 )) && echo -e "\nBUILD RUN #1" || echo ""
2358 ( (( $isPresentFlag == 1 )) | (( $isPresentFlag == 3 )) ) && cat "${RPM_BUILD_DIR}/.STATUS_1";
2359
2360 (( $isPresentFlag == 3 )) && echo -e "\n\n-------------------------------------------------------------------------------\n\nBUILD RUN #2" || echo -e ""
2361 ( (( $isPresentFlag == 2 )) | (( $isPresentFlag == 3 )) ) && cat "${RPM_BUILD_DIR}/.STATUS_2";
2362
2363 echo -e "\n\n-------------------------------------------------------------------------------\n"
2364
2365 elif (( $# > 0 )) && [[ ${1,,} =~ ^-+s(ide)?-?by?-?s(ide)?(=[0-9]+)?$ ]]; then
2366
2367 (( $isPresentFlag == 1 )) && cat "${RPM_BUILD_DIR}/.STATUS_1";
2368 (( $isPresentFlag == 2 )) && cat "${RPM_BUILD_DIR}/.STATUS_2";
2369
2370 if (( $isPresentFlag == 3 )); then
2371
2372 local diffWidth
2373 local lineCount1
2374 local lineCount2
2375 local nn=0
2376
2377 lineCount1="$(wc -l "${RPM_BUILD_DIR}/.STATUS_1" | sed -E s/'^([0-9]*) .*$'/'\1'/)"
2378 lineCount2="$(wc -l "${RPM_BUILD_DIR}/.STATUS_2" | sed -E s/'^([0-9]*) .*$'/'\1'/)"
2379
2380 # Transform lineCount{1,2} variables from raw number of lines into the
2381 # number of lines that need to be added to make the files have the same # of lines
2382
2383 if (( $lineCount1 < lineCount2 )); then
2384 lineCount2=$((( $lineCount2 - $lineCount1 )))
2385 lineCount1=0
2386
2387 elif (( $lineCount1 > lineCount2 )); then
2388 lineCount2=$((( $lineCount1 - $lineCount2 )))
2389 lineCount1=0
2390
2391 else # must be equal
2392 lineCount1=0
2393 lineCount2=0
2394 fi
2395
2396 [[ ${1,,} =~ ^-+s(ide)?-?by?-?s(ide)?=[0-9]+$ ]] && diffWidth="${1##*=}" || diffWidth=200
2397
2398 srpmAutoBuild_isMock && echo "TBD" || diff -y --width "${diffWidth}" <(echo -e "$(nn=0 && while (( $nn < $lineCount1 )); do echo -n '\n' && ((nn++)); done )"; echo "$(cat "${RPM_BUILD_DIR}/.STATUS_1")") <(echo -e "$(nn=0 && while (( $nn < $lineCount2 )); do echo -n '\n' && ((nn++)); done )"; echo "$(cat "${RPM_BUILD_DIR}/.STATUS_2")") #| sed -E s/' [\<\>\|]'/' '/g
2399 fi
2400
2401 echo -e "\n\n-------------------------------------------------------------------------------\n"
2402
2403 elif (( $# == 0 )) || [[ ! ${1,,} =~ ^-+s(imple)?$ ]]; then
2404
2405 (( $isPresentFlag == 3 )) && echo -e "\nBUILD RUN #1 \n\n" || echo -e "\n"
2406 ( (( $isPresentFlag == 1 )) | (( $isPresentFlag == 3 )) ) && cat "${RPM_BUILD_DIR}/.STATUS_1" | head -n -2 | sed -zE s'/^.*-{10}\n(.*)$'/'\n\1'/;
2407
2408 (( $isPresentFlag == 3 )) && echo -e "\n\n-------------------------------------------------------------------------------\n\nBUILD RUN #2 \n\n" || echo -e "\n"
2409 ( (( $isPresentFlag == 2 )) | (( $isPresentFlag == 3 )) ) && cat "${RPM_BUILD_DIR}/.STATUS_2" | head -n -2 | sed -zE s'/^.*-{10}\n(.*)$'/'\n\1'/;
2410
2411 echo -e "\n\n-------------------------------------------------------------------------------\n"
2412
2413 #[[ -f "${RPM_BUILD_DIR}/.STATUS_2" ]] && [[ -n $(cat "${RPM_BUILD_DIR}/.STATUS_2" | head -n -2 | sed -zE s'/^.*-{10}\n(.*)$'/'\n\1'/) ]] && ( echo -e "\n\nBUILD RUN #1: \n\n"; cat "${RPM_BUILD_DIR}/.STATUS_1" | head -n -2 | sed -zE s'/^.*-{10}\n(.*)$'/'\n\1'/; echo -e "\n\nBUILD RUN #2: \n\n"; cat "${RPM_BUILD_DIR}/.STATUS_2" ) || cat "${RPM_BUILD_DIR}/.STATUS_1" | head -n -2 | sed -zE s'/^.*-{10}\n(.*)$'/'\n\1'/
2414 fi
2415
2416 if [[ -f "${RPM_BUILD_DIR}/.STATS_OVERALL" ]] && [[ -n "$(cat "${RPM_BUILD_DIR}/.STATS_OVERALL")" ]]; then
2417 echo -e "\n||---------- OVERALL STATS----------||\n\n"
2418 cat "${RPM_BUILD_DIR}/.STATS_OVERALL"
2419 else
2420 local curStatusLine=""
2421 ( [[ -f "${RPM_BUILD_DIR}/.STATUS_1" ]] || [[ -f "${RPM_BUILD_DIR}/.STATUS_2" ]] ) && curStatusLine="$(cat ${RPM_BUILD_DIR}/.STATUS_* | grep -E '^CURRENT OVERALL PROGRESS \(All Build Runs\)\: ' | sort -V | tail -n 1)"
2422 ( [[ -f "${RPM_BUILD_DIR}/.STATUS_1" ]] || [[ -f "${RPM_BUILD_DIR}/.STATUS_2" ]] ) && curStatusLine="$(cat ${RPM_BUILD_DIR}/.STATUS_* | grep -E '^CURRENT PROGRESS\: ' | sort -V | tail -n 1)"
2423
2424 [[ -n "${curStatusLine}" ]] && echo "${curStatusLine}" || echo "CURRENT OVERALL PROGRESS (All Build Runs): $(cat ${RPM_BUILD_DIR}/.STATS_OVERALL)"
2425 fi
2426}
2427
2428srpmAutoBuild_setupStatsFiles() {
2429
2430 srpmAutoBuild_setEnvVars
2431 local nn=""
2432
2433 [[ -e "${RPM_BUILD_DIR}/.STATS_OVERALL" ]] && chmod 777 "${RPM_BUILD_DIR}/.STATS_OVERALL" && \rm -rf "${RPM_BUILD_DIR}/.STATS_OVERALL"
2434 touch "${RPM_BUILD_DIR}/.STATS_OVERALL" && chmod 777 "${RPM_BUILD_DIR}/.STATS_OVERALL"
2435
2436
2437 echo -e "\n||---------- OVERALL BUILD STATISTICS ----------|| \n\n# SPECS PROCESSED: \t\t 0" >> "${RPM_BUILD_DIR}/.STATS_OVERALL"
2438 for nn in {'# SUCCESSFUL BUILDS','# FAILED BUILDS','# SKIPPED BUILDS'}; do echo -e "${nn}: \t\t 0 ---> 0%" >> "${RPM_BUILD_DIR}/.STATS_OVERALL"; done
2439 echo -e '\n----------------------------------------\n' >> "${RPM_BUILD_DIR}/.STATS_OVERALL"
2440 for nn in {'SUCCESS ON 1ST BUILD ATTEMPT','SUCCESS ON 2ND BUILD ATTEMPT','SUCCESS ON 3RD BUILD ATTEMPT','SUCCESS ON 4TH BUILD ATTEMPT'}; do echo -e "${nn}: \t 0 ---> 0%" >> "${RPM_BUILD_DIR}/.STATS_OVERALL"; done
2441
2442}
2443
2444srpmAutoBuild_updateStatsFiles() {
2445 # input is nFailsCur from main loop
2446
2447 local keyCur=0
2448 local nn=0
2449 local numFields=0
2450 local -a fieldsCur
2451 local -a valsCur
2452 local -a countLabels=('1ST' '2ND' '3RD' '4TH')
2453
2454 [[ -f "${RPM_BUILD_DIR}/.STATS_OVERALL" ]] || echo ".STATS_OVERALL file not found" && return 1
2455 [[ ${1,,} =~ ^[0-4]$ ]] && keyCur=${1} || [[ "${1,,}" == "nan" ]] && keyCur=5 || echo "Invalid Input" && return 2
2456
2457 fieldsCur[0]='# SPECS PROCESSED'
2458
2459 (( $keyCur < 4 )) && fieldsCur[1]='# SUCCESSFUL BUILDS' || (( $keyCur == 4 )) && fieldsCur[1]='# FAILED BUILDS' || (( $keyCur == 5 )) && fieldsCur[1]='# SKIPPED BUILDS'
2460 (( $keyCur < 4 )) && fieldsCur[2]='SUCCESS ON '"${countLabels[$keyCur]}"' BUILD ATTEMPT'
2461
2462 numFields=${#fieldsCur[@]}
2463
2464 for nn in $(seq 0 $((( $numFields - 1 )))); do
2465 valsCur[$nn]=$((( $(cat "${RPM_BUILD_DIR}/.STATS_OVERALL" | grep -E '^'"${fieldsCur[$nn]//'#'/'\#'}" | sed -E s/'^[^0-9]*([0-9]*).*$'/'\1'/) + 1 )))
2466
2467 (( $nn == 0 )) && sed -iE s/'^('"${fieldsCur[$nn]//'#'/'\#'}"'[^0-9]*).*$'/'\1'"${valsCur[$nn]}"/ "${RPM_BUILD_DIR}/.STATS_OVERALL"
2468 (( $nn == 1 )) && sed -iE s/'^('"${fieldsCur[$nn]//'#'/'\#'}"'[^0-9]*).*$'/'\1'"${valsCur[$nn]} ---> $((( ( 100 * ${valsCur[$nn]} ) / ${valsCur[0]} )))%"/ "${RPM_BUILD_DIR}/.STATS_OVERALL"
2469 (( $nn == 2 )) && sed -iE s/'^('"${fieldsCur[$nn]//'#'/'\#'}"'[^0-9]*).*$'/'\1'"${valsCur[$nn]} ---> $((( ( 100 * ${valsCur[$nn]} ) / ${valsCur[0]} )))% (total) | $((( ( 100 * ${valsCur[$nn]} ) / ${valsCur[1]} )))% (of successful builds)"/ "${RPM_BUILD_DIR}/.STATS_OVERALL"
2470
2471 done
2472}
2473
2474
2475srpmAutoBuild_fixSpecFile_majorMinorMakedevError() {
2476 # $1 is the path of the specfile to fix
2477 # $2 is the name of the c source code file that caused the error (should be listed in the rpmbuild error message)
2478 # note: this fix is NOT automatically implemented. Manually implementing is easy, it just isnt automated. Just run the following:
2479 # `srpmAutoBuild_fixSpecFile_majorMinorMakedevError <specfile> <c-file>` and then re-try to build the specfile.
2480
2481 local cFile=""
2482 local specFileFull=""
2483
2484 cFile="${2}"
2485 if [[ "${cFile}" == *"/BUILD/"* ]]; then
2486 cFile="${cFile##*/BUILD/}"
2487 cFile="${cFile#*/}"
2488 fi
2489
2490 specFileFull="$(echo "$(cat "${1%.spec}.spec")")"
2491 specFileFull="$(echo "${specFileFull/'%build'/'%build sed -i -z -E s/'"'"'\n#include <'"'"'/'"'"'\n#include <sys\/sysmacros.h>\n#include <'"'"'/ '"${cFile}"}" | sed -z -E s/'\%build sed -i -z -E s'/'\%build\nsed -i -z -E s'/)"
2492
2493 echo "${specFileFull}" > "${1%'.spec'}.spec"
2494}
2495
2496srpmAutoBuild_checkBuildErrorLog() {
2497 # checks the error message log produced by the build to try to smartly auto-fix errors
2498 # $1: buildID
2499 # $2: specNameCur
2500
2501 [[ -f "${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${1}" ]] || return
2502
2503 # fix major/minor/makedev error
2504
2505 [[ -n "$(cat "${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${1}" | grep -E 'undefined reference to .?((major)|(minor)|(makedev))')" ]] && srpmAutoBuild_fixSpecFile_majorMinorMakedevError "${2}" "$(cat "${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${1}" | grep -E 'undefined reference to .?((major)|(minor)|(makedev))' | sed -E s/'^(.+ )?([^ ]*\.c)[\: ].*$'/'\2'/ | sort -u)"
2506
2507}
2508
2509
2510srpmAutoBuild_build() {
2511 # runs full build loop as a stand alone code to be used on either SRPMs or SPEC-files.
2512 #
2513 # input can be a srpm or a specfile. If it is an srpm then a specfile will be built into a specfile prior to the package being built.
2514 # build dependencies will automatically be installed, and many common rpm build errors will be dealt with automatically.
2515 # Basically everything happens automatically without needing additional user input after the function is called.
2516 #
2517 # 3 FLAGS are recognized that change the function behavior. These are not case sensitive, and can be in any input (not limited to first or last inputs)
2518 #
2519 # 1) REVERSEING THE BUILD ORDER. '-r' or '--reverse': reverse the order that the SPECs are built in. This allows for 2 build processes to run simultaneously and not overlap. Alternately, use '-nr' or '--no-reverse' to forse standard (alphabetical order). If not explicitly set, It will be set based on the build run type automatically. Typically, youll want to run the 1st builder on the SRPMS, let it finish installing build dependencies and building SPECs, and then after the 1st builder starts building the RPMs from the SPECS start the 2nd builder using the --reverse Flag (on the just-built spec-files, not the original srpms).
2520 #
2521 # 2) FORCE RE-BUILDING RPMS, EVEN IF ONE OF THE SAME NAME/VERSION/ARCH WAS ALREADY BUILT.'-f' or '--force': The code will by default look for already build RPMs, and if it finds a RPM in a directory indicating it was custom built (i.e., it is somewhere in either ${LOCALREPO_DIR}/built or ${RPM_BUILD_DIR}/RPMS) with the same name AND the same version, the spec-file isnt built. This Flag forces building the SRPM/SPEC, even if a match has been found indicating that it has already has been built and the RPM currently exists. The code will try to build all the SRPMs that it can, even if they exist already
2522 #
2523 # 3) DISABLING "FUZZY" MATCHING OF INPUTS WITHOUT AN EXACT FILE/DIRECTORY NAME MATCH. '-na' or '--no-auto' or '--no-auto-match': The code will by default try to match up inputs to existing files even if the input isnt a full filename match. Matches are looked for in the pwd and in the RPM build tree SRPM and SPEC directories. Matches in $(pwd) are prioritized. If the file extension is not given, the matching priority is: SPECS in pwd > srpms in pwd > specs in ${RPM_BUILD_DIR}/SPECS > srpms in in ${RPM_BUILD_DIR}/SRPMS. Enabling this Flag will require an exact filename match (either full or relative path, but exact nonetheless), and anything without an exact match is ignored.
2524 #
2525 # 4) FORCING BUILD RUN TYPE.
2526 # Use '-b1' or '--build(1|main|primary)' to force using build run #1 (primary run). This is the default, UNLESS both the following conditions are met: a) "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" does not exist, and b) both "${RPM_BUILD_DIR}/.BUILD_LIST_1" "${RPM_BUILD_DIR}/.STATUS_1" exist and are non empty and have PID identifiers different than the current build run. Note that using build run #1 will automatically set --no-reverse', unless '--reverse' is explicitly fgiven as an input.
2527 # Use '-b2' or '--build(2|secondary)' to force using build run #2 (secondary run). Note that using build run #2 will automatically set --reverse', unless '--no-reverse' is explicitly fgiven as an input.
2528 #
2529 # 5) RECURSIVE SEARCHING OF INPUT DIRECTORIES. By default, if any inputs are directories only the top level of that directory is scanned for SPECs and SRPMs. Use flag '-rec' or '--recursive' to include all subdirectories when scanning input directories for SPECs/SRPMs
2530 #
2531 # 6) FORCING THE USE OF SPECFILES
2532 # '-so' or '--specs-only': this will entirely ignore any SRPMs in the input. They will not be built into specs, nor into RPMs
2533 # '-sfr' or '--specs-force-rebuild': this will cause SRPMs to be rebuilt into specs, even if a specfile with the same name/version already exists in ${RPM_BUILD_DIR}/SPECS. The default behavior is to not rebuild SPECs, so long as both packasge name AND package version match between the SRPM and the SPEC-file.
2534 #
2535 # Note: the FLAGS actually recognized are slightly more general than what is shown here. example: you can add omit some (though not all) '-' characters (the 1st character must always be a '-' though)
2536
2537 # setup environment variables
2538 srpmAutoBuild_setEnvVars
2539
2540 local -a name_SPECS
2541 local -a name_SPECS_short
2542 local -a name_SRPMS
2543 local -a name_INPUT
2544 local -a nFailsAll
2545 local foundMatchCur=""
2546 local reverseOrderFlag
2547 local forceFlag=0
2548 local noAutoMatchFlag=0
2549 local recursiveDirSearchFlag=0
2550 local buildID=0
2551 local nn=0
2552 local nn2=""
2553 local kk=0
2554 local ff=0
2555 local ss=0
2556 local skipCurFlag=0
2557 local nSPECS=0
2558 local nameTemp=""
2559 local name_SPECS_builtFromSRPMS=""
2560 local built_dir=""
2561 local failed_dir=""
2562 local skipped_dir=""
2563 local rpmTempDir=""
2564 local buildID=0
2565 local specsOnlyFlag=0
2566 local specsForceRebuildFlag=0
2567
2568 rpmTempDir="$(srpmAutoBuild_getUniqueDir "${RPM_BUILD_DIR}/TEMP")"
2569
2570 while (( $# > 0 )); do
2571 if [[ ${1,,} =~ ^-+r(everse)?$ ]]; then
2572 reverseOrderFlag=1
2573 elif [[ ${1,,} =~ ^-+no?-?r(everse)?$ ]]; then
2574 reverseOrderFlag=0
2575 elif [[ ${1,,} =~ ^-+f(orce)?$ ]]; then
2576 forceFlag=$((( $forceFlag + 1 )))
2577 elif [[ ${1,,} =~ ^-+n(a|(o-?a(uto(-?match)?)?))$ ]]; then
2578 noAutoMatchFlag=$((( $noAutoMatchFlag + 1 )))
2579 elif [[ ${1,,} =~ ^-+b(1|(uild-?((main)|(primary)|1)))$ ]]; then
2580 buildID=1
2581 elif [[ ${1,,} =~ ^-+b(2|(uild-?((secondary)|2)))$ ]]; then
2582 buildID=2
2583 elif [[ ${1,,} =~ ^-+rec(ursive)?$ ]]; then
2584 recursiveDirSearchFlag=1
2585 elif [[ ${1,,} =~ ^-+s(pecs)?-?o(nly)?$ ]]; then
2586 specsOnlyFlag=1
2587 elif [[ ${1,,} =~ ^-+s(pecs)?-?f(orce)?-?r(ebuild)?$ ]]; then
2588 specsForceRebuildFlag=1
2589 else
2590 if [[ ${1} =~ ^[^\ ]+$ ]] && [[ $(realpath "${1}") =~ ^[^\ ]+$ ]]; then
2591 name_INPUT[$nn]="$(realpath "${1}")"
2592 elif [[ ${1} =~ ^[\ \t]*$ ]]; then
2593 # input is empty
2594 name_INPUT[$nn]=""
2595 else
2596 echo -e "\n\nWARNING: input \"${1}\" contains at least 1 space in its file path. This will break srpmAutoBuild in many ways. \nAs such, the specified file will be moved to \"${rpmTempDir}\" prior to being utilized by srpmAutoBuild. \n"
2597
2598 # move file. Remove any spaces present in filename aswell
2599 name_INPUT[$nn]="${rpmTempDir}/${1##*/}"
2600 name_INPUT[$nn]="${name_INPUT[$nn]// /__}"
2601 \mv -f "${1}" "${name_INPUT[$nn]}"
2602
2603 if [[ ! ${name_INPUT[$nn]} =~ ^[^\ \t]+$ ]]; then
2604 echo -e "\n\nCORRECTION: the SRPM / SPEC filename itself contains a space character (even after an automated attempt to remove spaces from the filename...). \nThis should never be the case for a spec or a srpm file. Since the file is probably invalid and would likely break everything, it will be dropped entirely. \n"
2605 name_INPUT[$nn]=""
2606 fi
2607 fi
2608 [[ -n "${name_INPUT[$nn]}" ]] && ((nn++))
2609 fi
2610 shift 1
2611 done
2612
2613 ### set default for empty input
2614 if (( $nn == 0 )) || [[ -z "${name_INPUT[*]}" ]]; then
2615 unset -v name_INPUT && declare -a name_INPUT
2616 name_INPUT[0]="${RPM_BUILD_DIR}/SPECS"
2617 (( $specsOnlyFlag == 0 )) && name_INPUT[1]="${RPM_BUILD_DIR}/SRPMS"
2618 fi
2619
2620 echo "nn = ${nn}"
2621 echo "name_INPUT = ${name_INPUT[@]}"
2622
2623 # remove temp dir if unused
2624 [[ -z "$(find "${rpmTempDir}" -maxdepth 1 -type f)" ]] && \rm -rf "${rpmTempDir}" && rpmTempDir=""
2625
2626 # if running in automatic mode, make the primary build run write an indicator to "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock". NO means it is currently building SPECS from SRPMS, and any positive numeric integer means all SPECS have been generated and have begun to be built into RPMS, empty/missing means 1st build run isnt active. 2nd build run always uses --reverse, so do not let the function be in control of the indicator is it uses rhe --reverse flag.
2627
2628 [[ -z "${BASHPID}" ]] && BASHPID="$(echo $$)"
2629
2630 if ( [[ -z ${buildID} ]] || (( $buildID == 0 )) ); then
2631 ( [[ ! -e "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" ]] && ( [[ -e "${RPM_BUILD_DIR}/.BUILD_LIST_1" ]] && [[ -n "$(cat "${RPM_BUILD_DIR}/.BUILD_LIST_1")" ]] && [[ "$(echo "$(cat "${RPM_BUILD_DIR}/.BUILD_LIST_1" | head -n 1)")" != "${BASHPID}" ]] ) && ( [[ -e "${RPM_BUILD_DIR}/.STATUS_1" ]] && [[ -n "$(cat "${RPM_BUILD_DIR}/.STATUS_1")" ]] && [[ "$(echo "$(cat "${RPM_BUILD_DIR}/.STATUS_1" | head -n 1)")" != "${BASHPID}" ]] ) && ( [[ -e "${RPM_BUILD_DIR}/.STATS_OVERALL" ]] && [[ -n "$(cat "${RPM_BUILD_DIR}/.STATS_OVERALL")" ]] ) ) && buildID=2 || buildID=1
2632 fi
2633
2634 ( (( $buildID == 1 )) || (( $buildID == 2 )) ) || buildID=1
2635 [[ -z ${reverseOrderFlag} ]] && reverseOrderFlag="$((( $buildID - 1 )))"
2636
2637 if (( $buildID == 1 )); then
2638 srpmAutoBuild_setupStatsFiles
2639 [[ -d "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" ]] && chmod 777 -R "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" && \mv -f "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" "$(srpmAutoBuild_getUniqueDir -n "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock.old")"
2640 [[ -f "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" ]] || touch "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" && chmod 777 "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock"
2641 fi
2642
2643 echo -ne "\n\nbuildID = ${buildID} ----> "; (( $buildID == 1 )) && echo "PRIMARY BUILD RUN STARTED" || echo "SECONDARY BUILD RUN STARTED"
2644
2645 [[ -e "${RPM_BUILD_DIR}/.BUILD_LIST_${buildID}" ]] && chmod 777 "${RPM_BUILD_DIR}/.BUILD_LIST_${buildID}" && \rm -rf "${RPM_BUILD_DIR}/.BUILD_LIST_${buildID}"
2646 [[ -e "${RPM_BUILD_DIR}/.STATUS_${buildID}" ]] && chmod 777 "${RPM_BUILD_DIR}/.STATUS_${buildID}" && \rm -rf "${RPM_BUILD_DIR}/.STATUS_${buildID}"
2647 echo -ne "\nBUILD PROCESS PID: "; echo "${BASHPID}" | tee "${RPM_BUILD_DIR}/.BUILD_LIST_${buildID}" "${RPM_BUILD_DIR}/.STATUS_${buildID}"
2648
2649 #(( $buildID > 0 )) && echo -e "\n\n||---------- PRIMARY BUILD RUN STARTED ----------|| \n" || echo -e "\n\n||---------- SECONDARY BUILD RUN STARTED ----------||\n\n"
2650 (( $specsOnlyFlag == 0 )) && echo -e "\n\nBuilding SRPM's into SPEC-files and prepping for main package building phase..." || echo -e "\n\nONLY EXISTING SPEC-FILES WILL BE USED. SRPM's will not be built into SPEC's."
2651
2652 nINPUT=${#name_INPUT[@]}
2653 echo "$nINPUT"
2654
2655 # expand files to full paths and call `realpath` (again). if any directories were passed as inputs, find any *.spec or *.src.rpm files in the top level of said directories, and add those to the build list.
2656
2657 for nn in $(seq 0 $((( $nINPUT - 1 )))); do
2658
2659 name_INPUT[$nn]="$(realpath "${name_INPUT[$nn]}")"
2660
2661 nameTemp=""
2662
2663 if [[ -d "${name_INPUT[$nn]}" ]]; then
2664
2665 name_INPUT[$nn]="$(echo "$(find "${name_INPUT[$nn]}" $( (( $recursiveDirSearchFlag == 0 )) && echo '-maxdepth 1') -type f -name "*.spec")"; echo "$(find "${name_INPUT[$nn]}" $( (( $recursiveDirSearchFlag == 0 )) && echo '-maxdepth 1') -type f -name "*.src.rpm")")"
2666
2667 elif ! [[ -f "${name_INPUT[$nn]}" ]] && (( noAutoMatchFlag == 0 )); then
2668
2669 nameTemp="$(find "${name_INPUT[$nn]%/*}" $( (( $recursiveDirSearchFlag == 0 )) && echo '-maxdepth 1') -type d -name "${nameTemp##*/}")"
2670
2671 if [[ -n "${nameTemp}" ]]; then
2672
2673 nameTemp2=($(echo "${nameTemp}"))
2674 nameTemp=""
2675
2676 for nn2 in "${nameTemp2[@]}"; do
2677 nameTemp="$(echo "${nameTemp}"; echo "$(find "${nn2}" $( (( $recursiveDirSearchFlag == 0 )) && echo '-maxdepth 1') -type f -name "*.spec")"; echo "$(find "${nn2}" $( (( $recursiveDirSearchFlag == 0 )) && echo '-maxdepth 1') -type f -name "*.src.rpm")")"
2678
2679 done
2680 fi
2681
2682 if [[ -z "${nameTemp}" ]] && (( $recursiveDirSearchFlag > 0 )); then
2683
2684 nameTemp="$(find "/" -type f -name "*${name_INPUT[$nn]}*")"
2685
2686 [[ -n "${nameTemp}" ]] && nameTemp="$(echo "$(echo "${nameTemp}" | grep -E '\.spec$' | sort -V; echo "${nameTemp}" | grep -E '\.src\.rpm$' | sort -V; echo "${nameTemp}" | grep -v -E '((\.spec)|(\.src\.rpm))$' | sort -V)")"
2687
2688 fi
2689
2690 [[ -n "${nameTemp// /}" ]] && name_INPUT[$nn]="${nameTemp}" || name_INPUT[$nn]=""
2691
2692 fi
2693
2694 done
2695
2696 name_INPUT=($(echo "${name_INPUT[@]}" | sort -u))
2697 echo "nINPUT: $nINPUT"
2698
2699 (( $specsOnlyFlag == 0 )) && nINPUT=${#name_INPUT[@]} || nINPUT=0
2700 echo "nINPUT: $nINPUT"
2701
2702 [[ -n "${name_INPUT[@]}" ]] && eval $( echo "${name_INPUT[@]}" | sed -E s/'^(.*)$'/'\[\[ -e "\1" \]\] \|\| '/ | sed -zE s/'\n'// | sed -zE s/'^(.*) \|\|[^a-zA-Z0-9]*$'/'\1'/ ) && chmod 777 "${name_INPUT[@]}"
2703
2704 # Try to match each input individually with an existing file and determine if the input is a specfile or srpm.
2705
2706 for nn in $(seq 0 $((( $nINPUT - 1 )))); do
2707
2708 name_INPUT[$nn]="$(realpath "${name_INPUT[$nn]}")"
2709 name_SPECS[$nn]=""
2710 name_SRPMS[$nn]=""
2711
2712 # set initial matching flag state
2713 if ! [[ -f "${name_INPUT[$nn]}" ]]; then
2714 foundMatchCur=0
2715 elif [[ ${name_INPUT[$nn]} == *.spec ]]; then
2716 foundMatchCur=1
2717 name_SPECS[$nn]="${name_INPUT[$nn]}"
2718 elif [[ ${name_INPUT[$nn]} == *.src.rpm ]]; then
2719 foundMatchCur=2
2720 name_SRPMS[$nn]="${name_INPUT[$nn]}"
2721 else
2722 foundMatchCur=0
2723 fi
2724
2725 if (( $foundMatchCur == 0 )) && (( $noAutoMatchFlag == 0 )); then
2726 # attempt smart matching to find a close match, since there wasnt an exact file match with correct file extension to the input
2727
2728 if [[ ${name_INPUT[$nn]} == *.spec ]]; then
2729 # definitely have a specfile. Check $(pwd) then check ${RPM_BUILD_DIR}/SPECS
2730
2731 if [[ -f "$(pwd)/${name_INPUT[$nn]##*/}" ]]; then
2732 name_SPECS[$nn]="$(find "$(pwd)" -type f -wholename "${name_INPUT[$nn]##*/}")"
2733 [[ -z "${name_SPECS[$nn]}" ]] && name_SPECS[$nn]="$(find "$(pwd)" -type f -name "${name_INPUT[$nn]##*/}")"
2734
2735 elif [[ -f "${RPM_BUILD_DIR}/SPECS/${name_INPUT[$nn]##*/}" ]]; then
2736 name_SPECS[$nn]="$(find "${RPM_BUILD_DIR}/SPECS" -type f -name "${name_INPUT[$nn]##*/}")"
2737
2738 else
2739 name_SPECS[$nn]="$(find / -type f -wholename "*${name_INPUT[$nn]}")"
2740 fi
2741
2742 [[ -n $(echo "${name_SPECS[$nn]}") ]] && foundMatchCur=1
2743
2744 elif [[ ${name_INPUT[$nn]} == *.src.rpm ]]; then
2745 # definitely have a srpm. Check $(pwd) then check ${RPM_BUILD_DIR}/SRPMS
2746
2747 if [[ -f "$(pwd)/${name_INPUT[$nn]##*/}" ]]; then
2748 name_SRPMS[$nn]="$(find "$(pwd)" -type f -wholename "${name_INPUT[$nn]}")"
2749 [[ -z "${name_SRPMS[$nn]}" ]] && name_SRPMS[$nn]="$(find "$(pwd)" -type f -name "${name_INPUT[$nn]##*/}")"
2750
2751 elif [[ -f "${RPM_BUILD_DIR}/SRPMS/${name_INPUT[$nn]##*/}" ]]; then
2752 name_SRPMS[$nn]="$(find "${RPM_BUILD_DIR}/SRPMS" -type f -name "${name_INPUT[$nn]##*/}")"
2753
2754 else
2755 name_SRPMS[$nn]="$(find / -type f -wholename "*${name_INPUT[$nn]}")"
2756 fi
2757
2758 [[ -n $(echo "${name_SRPMS[$nn]}") ]] && foundMatchCur=2
2759 fi
2760
2761 if (( $foundMatchCur == 0 )); then
2762 # no matches treating it as a filename with proper extension. Repeat matching search (first in $(pwd), then in ${RPM_BUILD_DIR}/<...>, but this time try adding either '.spec' or '.src.rpm' to the end of the given input.
2763
2764 if [[ -f "$(pwd)/${name_INPUT[$nn]##*/}.spec" ]]; then
2765 name_SPECS[$nn]="$(find "$(pwd)" -type f -wholename "${name_INPUT[$nn]}.spec")"
2766 [[ -z "${name_SPECS[$nn]}" ]] && name_SPECS[$nn]="$(find "$(pwd)" -type f -name "${name_INPUT[$nn]##*/}.spec")"
2767 [[ -n "${name_SPECS[$nn]}" ]] && foundMatchCur=1
2768
2769 elif [[ -n "$(find "$(pwd)" -type f -name "${name_INPUT[$nn]##*/}*.src.rpm")" ]]; then
2770 name_SRPMS[$nn]="$(find "$(pwd)" -type f -wholename "${name_INPUT[$nn]}.src.rpm")"
2771 [[ -z "${name_SRPMS[$nn]}" ]] && name_SRPMS[$nn]="$(find "$(pwd)" -type f -name "${name_INPUT[$nn]##*/}.src.rpm")"
2772 [[ -n "${name_SRPMS[$nn]}" ]] && foundMatchCur=2
2773
2774 elif [[ -f "${RPM_BUILD_DIR}/SPECS/${name_INPUT[$nn]##*/}.spec" ]]; then
2775 name_SPECS[$nn]="$(find "${RPM_BUILD_DIR}/SPECS" -type f -name "${name_INPUT[$nn]##*/}.spec")"
2776 [[ -n "${name_SPECS[$nn]}" ]] && foundMatchCur=1
2777
2778 elif [[ -n "$(find "${RPM_BUILD_DIR}/SRPMS" -type f -name "${name_INPUT[$nn]##*/}*.src.rpm")" ]]; then
2779 name_SRPMS[$nn]="$(find "${RPM_BUILD_DIR}/SRPMS" -type f -name "${name_INPUT[$nn]##*/}*.src.rpm")"
2780 [[ -n "${name_SRPMS[$nn]}" ]] && foundMatchCur=2
2781 fi
2782
2783 fi
2784
2785 fi
2786
2787 # if current file is not a spec-file, remove it from name_SPECS. If it, however, a srpm, add it to name_SRPMS. If it is neither drop it all together.
2788
2789 (( $foundMatchCur == 0 )) && echo "WARNING: ${name_INPUT[$nn]} could not be found as either a SPEC-file nor a SRPM package. It will NOT be built." && name_SPECS[$nn]="" && name_SRPMS[$nn]=""
2790
2791 (( $foundMatchCur == 1 )) && echo "NOTICE: ${name_INPUT[$nn]} was identified as a SPEC-file (${name_SPECS[$nn]##*/}). It will be built into a RPM." && name_SRPMS[$nn]=""
2792
2793 (( $foundMatchCur == 2 )) && echo "NOTICE: ${name_INPUT[$nn]} was identified as a SRPM (${name_SRPMS[$nn]##*/}). It will be built into a SPEC-file, and then built into a RPM." && name_SPECS[$nn]=""
2794
2795 done
2796
2797 echo "DONE ANALYSING INPUT FILES" && sleep 2
2798
2799 if (( $specsOnlyFlag == 1 )); then
2800
2801 echo "${name_INPUT[@]}"
2802 name_SPECS=($(echo "${name_INPUT[@]}" | grep -E '\.spec$'))
2803 name_SRPMS=($(echo -n ""))
2804
2805 for nn in $(seq 0 $((( ${#name_SPECS[@]} - 1 )))); do
2806 [[ ${name_SPECS[$nn]} == ${RPM_BUILD_DIR}/SPECS/* ]] || mv "${name_SPECS[$nn]}" "${RPM_BUILD_DIR}/SPECS/${name_SPECS[$nn]##*/}" && name_SPECS[$nn]="${RPM_BUILD_DIR}/SPECS/${name_SPECS[$nn]##*/}"
2807 done
2808
2809 # apply fix for weird naming issue
2810 #for nn in "${RPM_BUILD_DIR}/SPECS/"''$'\n'*; do
2811 # mv "${nn}" $(echo "${nn}" | sed -zE s/'SPECS\/\n'/'SPECS\/'/g)
2812 #done
2813
2814 else
2815 echo "STARTING TO BUILD SRPMS INTO SPECS..."
2816 echo "Determining and installing package dependencies for all SRPMS..." && sleep 2
2817
2818 # remove empty entries from specfile and srpm name arrays
2819 name_SPECS=($(echo ${name_SPECS[@]}))
2820 name_SRPMS=($(echo ${name_SRPMS[@]}))
2821
2822 # empty out ${RPM_BUILD_DIR}/SPECS directory
2823 rpmTempDir=""
2824 if [[ -n $(find "${RPM_BUILD_DIR}/SPECS" -maxdepth 1 -type f -name "*.spec") ]]; then
2825 rpmTempDir="$(srpmAutoBuild_getUniqueDir "${RPM_BUILD_DIR}/SPECS/.temp")"
2826 mv ${RPM_BUILD_DIR}/SPECS/*.spec "${rpmTempDir}"
2827 fi
2828
2829 # check/download/install builddeps using th input SPED-files and SRPMs, then build SPEC-files from all the input SRPMs.
2830
2831 #srpmAutoBuild_builddep "$(echo "${name_SPECS[*]} ${name_SRPMS[*]}" | sed -zE s/' +'/'\n'/g | sed -zE s/'\n+'/'\n'/g | sed -zE s/'^(.*[^\n])\n*$'/'\1'/)"
2832 srpmAutoBuild_builddep "${name_SRPMS[@]}"
2833
2834 echo "Build dependencies downloaded. Starting to build SRPMs into SPEC-files" && sleep 2
2835
2836 srpmAutoBuild_build_SRPM_SPEC "-f$((( ( 2 * $forceFlag ) + $specsForceRebuildFlag )))" "${name_SRPMS[@]}"
2837
2838 # apply fix for weird naming issue
2839 #for nn in "${RPM_BUILD_DIR}/SPECS/"''$'\n'*; do
2840 # mv "${nn}" $(echo "${nn}" | sed -zE s/'SPECS\/\n'/'SPECS\/'/g)
2841 #done
2842
2843 name_SPECS_builtFromSRPMS="$(find "${RPM_BUILD_DIR}/SPECS" -maxdepth 1 -type f -name "*.spec")"
2844
2845 # re-check/download/install builddeps using the newly generated specfiles.
2846 # If you are building more than a couple packages, there will usually be a handful of build dependencies that were missing / not parsed correctly from the srpm's but that can be parsed correctly from the spec-files.
2847 srpmAutoBuild_builddep "${name_SPECS_builtFromSRPMS}"
2848
2849 name_SPECS=($(echo "$(echo "${name_SPECS[@]}" | sed -zE s/' +'/'\n'/g | sed -zE s/'\n+'/'\n'/g | sed -zE s/'^(.*[^\n])\n*$'/'\1'/ ; echo "${name_SPECS_builtFromSRPMS}")" | sort -u))
2850
2851 # if stuff was initially moved out of ${RPM_BUILD_DIR}/SPECS, put it back. Dont overwrite the newer spec's if there are any matching ones
2852 if [[ -n "${rpmTempDir}" ]]; then
2853 \mv -u ${rpmTempDir}/*.spec "${RPM_BUILD_DIR}/SPECS/"
2854 \rm -rf "${rpmTempDir:?}/"
2855 rpmTempDir=""
2856 fi
2857
2858 fi
2859
2860 # short name: no file path, no '.spec', just the package name.
2861 name_SPECS_short=($(echo "${name_SPECS[@]}" | sed -zE s/' +'/'\n'/g | sed -zE s/'\n+'/'\n'/g | sed -zE s/'^(.*[^\n])\n*$'/'\1'/ | sed -E s/'^.*\/([^\/]*)\.spec(\.old)?$'/'\1'/))
2862
2863 nSPECS=${#name_SPECS[@]}
2864 echo "# specfiles: $nSPECS"
2865
2866 # standard build order
2867 nnALL=($(seq 0 $((( $nSPECS - 1 )))))
2868
2869 echo "${nnALL}"
2870
2871 # reverse order if Flag was given
2872 (( $reverseOrderFlag > 0 )) && nnALL=($(echo "${nnALL[@]}" | sed -E s/' '/'\n'/g | sort -nr))
2873
2874
2875 # Setup BUILT and FAILED directories to move specs into after they are finished being processed.
2876 # If these directories exist from previous builds, enumerate them and place them in directories BUILT_OLD and FAILED_OLD
2877
2878 [[ -d "${RPM_BUILD_DIR}" ]] || mkdir "${RPM_BUILD_DIR}"
2879 chmod 777 $(find "${RPM_BUILD_DIR}" -maxdepth 1 -type d)
2880
2881 built_dir="${RPM_BUILD_DIR}/SPECS/BUILT"
2882 failed_dir="${RPM_BUILD_DIR}/SPECS/FAILED"
2883 skipped_dir="${RPM_BUILD_DIR}/SPECS/SKIPPED"
2884 rpmTempDir=""
2885
2886 if [[ -d "${built_dir}" ]]; then
2887 [[ -d "${built_dir}_OLD" ]] || mkdir "${built_dir}_OLD"
2888 \mv -f "${built_dir}" "$(srpmAutoBuild_getUniqueDir -n "${built_dir}_OLD/")"
2889 fi
2890 [[ -d "${built_dir}" ]] || mkdir --parents "${built_dir}"
2891
2892
2893 if [[ -d "${failed_dir}" ]]; then
2894 [[ -d "${failed_dir}_OLD" ]] || mkdir "${failed_dir}_OLD"
2895 \mv -f "${failed_dir}" "$(srpmAutoBuild_getUniqueDir -n "${failed_dir}_OLD/")"
2896 fi
2897 [[ -d "${failed_dir}" ]] || mkdir --parents "${failed_dir}"
2898
2899 if [[ -d "${skipped_dir}" ]]; then
2900 [[ -d "${skipped_dir}_OLD" ]] || mkdir "${skipped_dir}_OLD"
2901 \mv -f "${skipped_dir}" "$(srpmAutoBuild_getUniqueDir -n "${skipped_dir}_OLD/")"
2902 fi
2903 [[ -d "${skipped_dir}" ]] || mkdir --parents "${skipped_dir}"
2904
2905
2906 (( $buildID == 1 )) && [[ -f "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" ]] && chmod 777 "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" && \rm -f "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock"
2907
2908 nFailsAll=(0 0 0 0 0 0)
2909
2910 echo -e "\n\nMAIN BUILD LOOP IS NOW STARTING \n\n"
2911
2912 [[ -z "${forceFlag}" ]] && forceFlag=0
2913
2914 for nn in "${nnALL[@]}"; do
2915
2916 # get current spec name and reset failed build count.
2917 nameSpecCur="${name_SPECS[$nn]}"
2918 nFailsCur=0
2919 skipCurFlag=0
2920 nameRpmCur=""
2921
2922 [[ "${nameSpecCur}" == "$(echo -n "$(cat "${RPM_BUILD_DIR}/.BUILD_LIST_$((( 3 - $buildID )))" | tail -n 1)")" ]] && skipCurFlag=3 || echo "${nameSpecCur}" >> "${RPM_BUILD_DIR}/.BUILD_LIST_${buildID}"
2923
2924 # check that the specfile exists, and look for matching rpm packages with the same name+version
2925
2926 (( $skipCurFlag == 0 )) && ( [[ -z "${nameSpecCur}" ]] || [[ -d "${nameSpecCur}" ]] || [[ ! -f "${nameSpecCur}" ]] ) && skipCurFlag=2
2927
2928 (( $skipCurFlag == 0 )) && nameRpmCur="$(srpmAutoBuild_getInfo -n -v -a $(find {"${RPM_BUILD_DIR}/RPMS","${LOCALREPO_DIR}/built"} -type f -name "*$(srpmAutoBuild_getInfo -n "${nameSpecCur}")*.rpm" | grep -v '/cache/'))" && [[ -n "${nameRpmCur}" ]] && [[ -n "$( echo "${nameRpmCur}" | grep -F "$(srpmAutoBuild_getInfo -n -v -a "${nameSpecCur}")")" ]] && skipCurFlag=1
2929 # "${name_SPECS_short[$nn]}-$(rpm --eval "$(cat "${nameSpecCur}" | grep -E '^Version\:' | sed -E s/'^[^\:]*\:[ \t]*(.*)$'/'\1'/)")*.rpm" | sed -E s/'^.*\/([^\/]*)$'/'\1'/)"
2930
2931 # (( $skipCurFlag == 0 )) && [[ -n "${nameRpmCur}" ]] && skipCurFlag=1
2932 # "$(find "${LOCALREPO_DIR}/built" -type f -name "${name_SPECS_short[$nn]}-$(rpm --eval "$(cat "${nameSpecCur}" | grep -E '^Version\:' | sed -E s/'^[^\:]*\:[ \t]*(.*)$'/'\1'/)")*.rpm" | sed -E s/'^.*\/([^\/]*)$'/'\1'/)"
2933
2934 echo -e "\n\nDEBUG INFO: \n\nnameSpecCur=${nameSpecCur} \nnameRpmCur=${nameRpmCur} \nskipCurFlag=${skipCurFlag} \n\n"
2935
2936 if (( $skipCurFlag <= $forceFlag )); then
2937
2938 # print status
2939 echo -e "\n\nBEGINNING BUILD # $((( $nn + 1 ))) of ${nSPECS}: ${name_SPECS_short[$nn]}.spec \n\n"
2940
2941 # check for missing builddeps, with erasing allowed. This is usually very quick as long as it isnt missing any dependencies, which should be the case for most packages.
2942 dnf builddep --skip-broken --allowerasing -y "${name_SPECS_short[$nn]}"
2943
2944 # Set environment variables to default, in case they were changed
2945 srpmAutoBuild_setEnvVars
2946
2947 [[ -f "${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${buildID} " ]] && chmod 777 "${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${buildID}" && \rm -f "${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${buildID}"
2948 touch "${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${buildID}"
2949
2950 # initial build attempt: try to force generation of debuginfo
2951 nFailsCur=0
2952 QA_RPATHS=$(( 0x0001|0x0010 )) rpmbuild --rpmfcdebug -bb "${nameSpecCur}" 2>${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${buildID} || nFailsCur=1 && srpmAutoBuild_checkBuildErrorLog "${buildID}" "${nameSpecCur}"
2953
2954 if (( $nFailsCur == 1 )); then
2955 # 2nd try: modify spec file to not throw an error in debug source file list is missing. Save orig as *.spec.old
2956 srpmAutoBuild_fixSpecFile_missingDebugSourceFileList "${nameSpecCur}"
2957 QA_RPATHS=$(( 0x0001|0x0010 )) rpmbuild -bb "${nameSpecCur}" 2>${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${buildID} || nFailsCur=2 && srpmAutoBuild_checkBuildErrorLog "${buildID}" "${nameSpecCur}"
2958 fi
2959
2960 if (( $nFailsCur == 2 )); then
2961 # 3rd try: switch back to original spec file. Add '-Wno-error' Flag to CFlag/CXXFlag/CPPFlag env variables. allow build to proceed in cases where there are unpackaged files or missing documentation.
2962 srpmAutoBuild_setEnvVars '-Wno-error'
2963 srpmAutoBuild_switchSpecFile "${nameSpecCur}"
2964 QA_RPATHS=$(( 0x0001|0x0010 )) rpmbuild -bb --define=" _unpackaged_files_terminate_build 0" --define=" _missing_doc_files_terminate_build 0" "${nameSpecCur}" 2>${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${buildID} || nFailsCur=3 && srpmAutoBuild_checkBuildErrorLog "${buildID}" "${nameSpecCur}"
2965 fi
2966
2967 if (( $nFailsCur == 3 )); then
2968 # 4th try: (last try) same as 3rd try, but with the modifies specfile that allows missing debug source list
2969 srpmAutoBuild_switchSpecFile "${nameSpecCur}"
2970 QA_RPATHS=$(( 0x0001|0x0010 )) rpmbuild -bb --define=" _unpackaged_files_terminate_build 0" --define=" _missing_doc_files_terminate_build 0" "${nameSpecCur}" 2>${RPM_BUILD_DIR}/.BUILD_ERROR_LOG_${buildID} || nFailsCur=4 && srpmAutoBuild_checkBuildErrorLog "${buildID}" "${nameSpecCur}"
2971 fi
2972
2973 if (( $nFailsCur == 4 )); then
2974 # all tries failed. Add 1 to failed count, switch the specfile back to the original, and move the orig + modded spec files into "FAILED" directory
2975 ((ff++)) #ff=$((( $ff + 1 )))
2976 srpmAutoBuild_switchSpecFile "${nameSpecCur}"
2977 mv "${nameSpecCur}" "${nameSpecCur}.old" "${failed_dir}"
2978 else
2979 # build succeeded. Add 1 to success count and move specfile + modded spec file (if it exists) into "BUILT" directory
2980 ((kk++)) #kk=$((( $kk + 1 )))
2981 mv "${nameSpecCur}" "${built_dir}"
2982 [[ -f "${nameSpecCur}.old" ]] && mv "${nameSpecCur}.old" "${built_dir}"
2983 fi
2984
2985 # reset environment variables
2986 srpmAutoBuild_setEnvVars
2987
2988
2989 # update total failure type stats array
2990 nFailsAll[$nFailsCur]=$((( ${nFailsAll[$nFailsCur]} + 1 )))
2991
2992 else
2993
2994 # print message saying spec file was skipped and why it wasnt built
2995 echo -e "\n\nNOTICE: ${nameSpecCur} was excluded from being built. It was skipped for the following reasons: \n"
2996 (( $skipCurFlag == 3)) && echo -e "\n\n----> This specfile is currently being built by the other build process. \n\n"
2997 (( $skipCurFlag == 2 )) && echo -e "\n\n----> A matching RPM with the same package name and version was found in ${RPM_BUILD_DIR}/RPMS, suggesting that this SPEC file has already been built. \n\nNOTE: To ignore matching already built RPMS and force (re)building, use 'srpmAutoBuild_buildSA --force'. Note that this will overwrite the existing RPM, should it exist in ${RPM_BUILD_DIR}/RPMS. \n\n"
2998 (( $skipCurFlag == 1 )) && echo -e "\n\n----> The input SPEC-file could not be located (and/or read, if insufficient permissions). \n\n"
2999
3000 # add 1 to skipped count and set # current run failures to NaN
3001 ((ss++)) #ss=$((( $ss + 1 )))
3002 nFailsCur="NaN${skipCurFlag}"
3003 nFailsAll[5]=$((( ${nFailsAll[5]} + 1 )))
3004 mv "${nameSpecCur}" "${skipped_dir}"
3005
3006 fi
3007
3008 # Print info about the result of the current run and stats for all runs completed so far
3009 srpmAutoBuild_updateStatsFiles "${nFailsCur}"
3010 echo -e "\n\n-------------------------------------------------------------------------------\n\nCURRENT BUILD OPERATION HAS FINISHED! BUILD STATS: \n\nSPECFILE NAME: \"${name_SPECS_short[$nn]}\" ( ID# $((( $nn + 1 ))) / ${nSPECS} ) $(srpmAutoBuild_printBuildStats "${nn}" "${nFailsCur}" "${kk}" "${ff}" "${ss}" "${nSPECS}" ${nFailsAll[@]} "${skipCurFlag}" "${buildID}") \n\n-------------------------------------------------------------------------------\n" | tee -a "${RPM_BUILD_DIR}/.STATUS_${buildID}"
3011
3012 #echo $((( $(echo "$(cat "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock")") + 1 ))) > "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock"
3013
3014 done
3015
3016 #(( $buildID > 0 )) && \rm -f "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock" && touch "${RPM_BUILD_DIR}/.SECONDARY_BUILD.lock"
3017
3018}
3019
3020
3021# # # # # # # # # # EXTRA FUNCTIONS FOR MANAGING A LOCAL REPOSITORY # # # # # # # # # #
3022
3023# run `localrepo_updateDatabase` to have everything done automatically for you. The rest of the functions are supporting functions for localrepo_updateDatabase
3024# exception: localrepo_showFileTree shows the file tree,, and is for informational purposes only. Other than showing the filetree it doesnt do anything.
3025#
3026# the following environment variables will be used, if they exist:
3027# LOCALREPO_DIR: path to main localrepo dir. Default is '/localrepo'
3028# LOCALREPO_NAME: name of the main localrepo. Default is 'localrepo'
3029# VALID_ARCH_LIST: space separated lists of valid architectures. Default is "noarch x86_64 i686"
3030# LOCALREPO_BACKUP_DIR: directory to store backup in. If /DATA/${LOCALREPO_DIR#/}, exists, it will be used unless LOCALREPO_BACKUP_DIR is defined otherwise. If neither LOCALREPO_BACKUP_DIR nor /DATA/${LOCALREPO_DIR#/} the repo wont automatically make a backup copy
3031# FEDORA_COMPS_FILE_PATH: path to the fedora comps file, needed to use groups in dnf. Default location is ${LOCALREPO_DIR}/fedora-comps/comps-f29.xml". If this doesnt exist the code will set it up automatically
3032
3033
3034localrepo_dnf() {
3035 # runs `dnf` with only localrepo as the only active repository active
3036 # use flag '-name' as the 1st input to change 'localrepo' to 'localrepo-name'.
3037 # with default localrepo settings this shiould be '-build', '-source', or '-downloaded'.
3038 # ---> restrict packages to thoise in 'localrepo-[built|source|download]' instead of the full localrepo
3039
3040 # change this (or set env variable LOCALREPO_NAME if your local repo isnt called 'localrepo'
3041 local localrepoName=""
3042 [[ -n "${LOCALREPO_NAME}" ]] && localrepoName="${LOCALREPO_NAME}" || localrepoName='localrepo'
3043
3044 [[ ${1,,} =~ ^-+.+$ ]] && localrepoName="${localrepoName}-${1//'-'/''}" && echo "using repo: ${localrepoName}" && shift 1
3045
3046 dnf --refresh --skip-broken --disablerepo=[a-zA-Z0-9]* --enablerepo=${localrepoName} ${@}
3047
3048}
3049
3050localrepo_setEnvVars() {
3051
3052 # setup LOCALREPO_DIR
3053 ( [[ -z "${LOCALREPO_DIR}" ]] || [[ ${1} =~ ^-+c(lea[nr])?$ ]] ) && LOCALREPO_DIR="/localrepo" && echo -e "\nLOCALREPO_DIR set to: '${LOCALREPO_DIR}' \n" && export LOCALREPO_DIR || [[ "${LOCALREPO_DIR}" != "${LOCALREPO_DIR%/}" ]] && LOCALREPO_DIR="${LOCALREPO_DIR%/}" && echo -e "\nLOCALREPO_DIR set to: '${LOCALREPO_DIR}' \n" && export LOCALREPO_DIR
3054
3055 # setup VALID_ARCH_LIST
3056 [[ -z "${VALID_ARCH_LIST}" ]] && VALID_ARCH_LIST="$(echo "noarch"; uname -pmi | sed -zE s/' '/'\n'/g | sort -u; [[ "$(uname -pmi | sed -zE s/' '/'\n'/g | sort -u)" == "x86_64" ]] && echo "i686" )" && export VALID_ARCH_LIST
3057
3058 # setup LOCALREPO_BACKUP_DIR
3059 [[ -z "${LOCALREPO_BACKUP_DIR}" ]] && [[ -d "/DATA/${LOCALREPO_DIR#/}" ]] && LOCALREPO_BACKUP_DIR="/DATA/${LOCALREPO_DIR#/}" && echo -e "\nLOCALREPO_BACKUP_DIR set to: '${LOCALREPO_BACKUP_DIR}' \n" && export LOCALREPO_BACKUP_DIR
3060
3061 # setup FEDORA_COMPS_FILE_PATH
3062 [[ -z "${FEDORA_COMPS_FILE_PATH}" ]] && FEDORA_COMPS_FILE_PATH="${LOCALREPO_DIR}/fedora-comps/comps-f$(uname -r | sed -E s/'^.*\.fc([0-9]*)\..*$'/'\1'/).xml" && export FEDORA_COMPS_FILE_PATH
3063
3064}
3065
3066localrepo_makeFileTree() {
3067 # makes all the directories in ${LOCALREPO_DIR} that are required by the localrepo_* functions but do not yet exist
3068
3069 # define local repo path and list valid architectures
3070 localrepo_setEnvVars
3071
3072 local -a vaArray
3073 [[ -n "${VALID_ARCH_LIST}" ]] && vaArray=(${VALID_ARCH_LIST}) || vaArray=($(echo "noarch"; uname -pmi | sed -zE s/' '/'\n'/g | sort -u; [[ "$(uname -pmi | sed -zE s/' '/'\n'/g | sort -u)" == "x86_64" ]] && echo "i686" ))
3074
3075 [[ -d "${LOCALREPO_DIR}" ]] || mkdir --parents "${LOCALREPO_DIR}"
3076 [[ -d "${LOCALREPO_DIR}/cache" ]] || mkdir "${LOCALREPO_DIR}/cache"
3077 [[ -d "${LOCALREPO_DIR}/.MISC" ]] || mkdir "${LOCALREPO_DIR}/.MISC"
3078 [[ -d "${LOCALREPO_DIR}/.REMOVED" ]] || mkdir "${LOCALREPO_DIR}/.REMOVED"
3079
3080 for ll in {source/,built/,downloaded/,built/debuginfo/,downloaded/debuginfo/}; do
3081 for mm in {"",${vaArray[@]}}; do
3082
3083 if ( [[ "${ll}" == "source/" ]] && [[ -z "${mm}" ]] ) || ( [[ "${ll}" != "source/" ]] && [[ -n "${mm}" ]] ); then
3084
3085 for nn in {a..z} {0..9}; do
3086 [[ -d "${LOCALREPO_DIR}/${ll}/${mm}packages/${nn}" ]] || mkdir --parents "${LOCALREPO_DIR}/${ll}/${mm}packages/${nn}"
3087 done
3088
3089 [[ -d "${LOCALREPO_DIR}/${ll}${mm}cache" ]] || mkdir --parents "${LOCALREPO_DIR}${ll}/${mm}cache"
3090
3091 fi
3092
3093 if [[ ${ll} != */debuginfo ]]; then
3094
3095 [[ -d "${LOCALREPO_DIR}/${ll}/NEW" ]] || mkdir "${LOCALREPO_DIR}/${ll}/NEW"
3096 [[ -d "${LOCALREPO_DIR}/.REMOVED/${ll}" ]] || mkdir "${LOCALREPO_DIR}/.REMOVED/${ll}"
3097
3098 fi
3099
3100 done
3101 done
3102
3103}
3104
3105
3106localrepo_importBuiltRPMs() {
3107 # transfers RPMs from paths used by default by rpmbuild and srpmAutoBuild (~/rpmbuild and /builddir./build) into the local repo's ${LOCALREPO_DIR}/*/NEW folders
3108
3109 # define local repo path
3110 localrepo_setEnvVars
3111
3112 local uu=""
3113
3114 # copy (S)RPMs from user rpmbuild trees into NEW directories
3115 for uu in {/root,/home/*}; do
3116 [[ -d "${uu}/rpmbuild/RPMS/" ]] && [[ -n $(find "${uu}/rpmbuild/RPMS/" -type f -name "*.rpm") ]] && chmod -R 775 ${uu}/rpmbuild/RPMS/* && \cp -u $(find "${uu}/rpmbuild/RPMS/" -type f -name "*.rpm") "${LOCALREPO_DIR}/built/NEW"
3117 [[ -d "${uu}/rpmbuild/SRPMS/" ]] && [[ -n $(find "${uu}/rpmbuild/SRPMS/" -type f -name "*.src.rpm") ]] && chmod -R 775 ${uu}/rpmbuild/SRPMS/* && \cp -u $(find "${uu}/rpmbuild/SRPMS/" -type f -name "*.src.rpm") "${LOCALREPO_DIR}/source/NEW"
3118 done
3119
3120 # copy (S)RPMs from srpmAutoBuild's RPM_BUILD_DIR into NEW directories
3121 if [[ -n "${RPM_BUILD_DIR}" ]] && [[ -d "${RPM_BUILD_DIR}" ]]; then
3122 [[ -n $(find "${RPM_BUILD_DIR}/RPMS/" -type f -name "*.rpm") ]] && \cp -u $(find "${RPM_BUILD_DIR}/RPMS/" -type f -name "*.rpm") "${LOCALREPO_DIR}/built/NEW"
3123 [[ -n $(find "${RPM_BUILD_DIR}/SRPMS/" -type f -name "*.src.rpm") ]] && \cp -u $(find "${RPM_BUILD_DIR}/SRPMS/" -type f -name "*src.rpm") "${LOCALREPO_DIR}/source/NEW"
3124 fi
3125
3126 # copy (S)RPMs from the mock build dir used by srpmAutoBuild into NEW directories
3127 if [[ -n "${MOCK_ROOT_DIR}" ]] && [[ -d "${MOCK_ROOT_DIR}/builddir/build" ]] && [[ "${RPM_BUILD_DIR}" != "${MOCK_ROOT_DIR}/builddir/build" ]]; then
3128 [[ -n $(find "${RPM_BUILD_DIR}/RPMS/" -type f -name "*.rpm") ]] && \cp -u $(find "${MOCK_ROOT_DIR}/builddir/build/RPMS/" -type f -name "*.rpm") "${LOCALREPO_DIR}/built/NEW"
3129 [[ -n $(find "${RPM_BUILD_DIR}/SRPMS/" -type f -name "*.src.rpm") ]] && \cp -u $(find "${MOCK_ROOT_DIR}/builddir/build/SRPMS/" -type f -name "*src.rpm") "${LOCALREPO_DIR}/source/NEW"
3130 fi
3131}
3132
3133
3134localrepo_downloadMissingRPMs() {
3135 # download any installed RPMS that are not ye(yet) built
3136 # this was originally intended to allow for re-creating a image of the system (via lorax) with the online repos completely disabled and all packages being sourced from this local repo
3137
3138 # define local repo path
3139 localrepo_setEnvVars
3140
3141 local missingRpmList=""
3142
3143 # find rpms not in built or downloaded and download to "${LOCALREPO_DIR}/downloaded/NEW"
3144
3145 missingRpmList="$(diff -ywd --tabsize=1 --width=512 --suppress-common-lines <(rpm -qa | sort -u) <(find ${LOCALREPO_DIR}/{built,downloaded} -type f -name "*.rpm" | sed -E s/'^.*\/([^\/]*)\.rpm$'/'\1'/ | sort -u) | grep -v -E '\>' | grep -E '[\<\|]' | sed -E s/'^([^\<\|]*)[\<\|].*$'/'\1'/ | sort -u)"
3146
3147 [[ -n "${missingRpmList}" ]] && cd "${LOCALREPO_DIR}/downloaded/NEW" && dnf download --skip-broken ${missingRpmList} && cd "${OLDPWD}"
3148
3149}
3150
3151
3152localrepo_sortNewRPMs() {
3153 # looks in user's rpmbuild trees for new RPMs and moves them into */NEW, then sorts all the RPMs int eh */NEW directories into the proper package directories
3154
3155 # define local repo path and list valid architectures
3156 localrepo_setEnvVars
3157
3158 local -a vaArray
3159 [[ -n "${VALID_ARCH_LIST}" ]] && vaArray=(${VALID_ARCH_LIST}) || vaArray=($(echo "noarch"; uname -pmi | sed -zE s/' '/'\n'/g | sort -u; [[ "$(uname -pmi | sed -zE s/' '/'\n'/g | sort -u)" == "x86_64" ]] && echo "i686" ))
3160
3161 local ll=""
3162 local mm=""
3163 local nn=""
3164
3165 # set user:group to root:wheel if we can
3166 [[ "${USER}" == "root" ]] && chown -R root:wheel ${LOCALREPO_DIR}/{source,built,downloaded}/NEW && chmod -R 775 ${LOCALREPO_DIR}/{source,built,downloaded}/NEW
3167
3168 for nn in {0..9} {a..z} {A..Z}; do
3169
3170 # sort source srpms into source/packages/* folders
3171 [[ -n "$(find "${LOCALREPO_DIR}/source/NEW" -type f -name "${nn}*.src.rpm")" ]] && \mv -f $(find "${LOCALREPO_DIR}/source/NEW" -type f -name "${nn}*.src.rpm") "${LOCALREPO_DIR}/source/packages/${nn,,}/"
3172
3173 done
3174
3175 for ll in {built,downloaded}; do
3176 for mm in "${vaArray[@]}"; do
3177 for nn in {0..9} {a..z} {A..Z}; do
3178
3179 # sort {built,downloaded} rpms into {built,downloaded}/packages/* folders
3180 [[ -n "$(find "${LOCALREPO_DIR}/${ll}/NEW" -type f -name "${nn}*.${mm}.rpm" | grep -v -E 'debug(source|info)')" ]] && \mv -f $(find "${LOCALREPO_DIR}/${ll}/NEW" -type f -name "${nn}*.${mm}.rpm" | grep -v -E 'debug(source|info)') "${LOCALREPO_DIR}/${ll}/${mm}/packages/${nn,,}/"
3181
3182 # sort debug info for {built,downloaded} rpms into {built,downloaded}/debuginfo/packages/* folders
3183 [[ -n "$(find "${LOCALREPO_DIR}/${ll}/NEW" -type f -name "${nn}*.${mm}.rpm" | grep -E 'debug(source|info)')" ]] && \mv -f $(find "${LOCALREPO_DIR}/${ll}/NEW" -type f -name "${nn}*.${mm}.rpm" | grep -E 'debug(source|info)') "${LOCALREPO_DIR}/${ll}/debuginfo/${mm}/packages/${nn,,}/"
3184
3185 done
3186 done
3187 done
3188
3189}
3190
3191
3192localrepo_fixSorting_debuginfo() {
3193 # move debug packages into debuginfo dirs, and move any packages that arent debuginfo out of debuginfo dirs
3194 # localrepo_sortNewRPMs *should* sort everything correctly, but this function runs very fast so running it is worthwhile
3195
3196 # define local repo path
3197 localrepo_setEnvVars
3198
3199 # move mis-sorted debug packages in standard folders into debuginfo folders.
3200 # If duplicates already exists in debuginfo folder: overwrite if the other is newer, otherwise move the other one to the REMOVED folder
3201 if [[ -n "$(find ${LOCALREPO_DIR}/{built,downloaded}/*/packages -type f -name "*debug*.rpm" | grep -E '^.*\/[^\/]*-debug(source|info)-[^\/]*$')" ]]; then
3202
3203 eval $(find ${LOCALREPO_DIR}/{built,downloaded}/*/packages -type f -name "*debug*.rpm" | grep -E '^.*\/[^\/]*-debug(source|info)-[^\/]*$' | sed -E s/'^(.*)\/(built|downloaded)\/(.*)$'/'\\mv -u "\1\/\2\/\3" "\1\/\2\/debuginfo\/\3\";'/)
3204 eval $(find ${LOCALREPO_DIR}/{built,downloaded}/*/packages -type f -name "*debug*.rpm" | grep -E '^.*\/[^\/]*-debug(source|info)-[^\/]*$' | sed -E s/'^(.*)\/(built|downloaded)\/(.*)$'/'\\mv -f "\1\/\3" "\1\/\.REMOVED\/\2";'/)
3205
3206 fi
3207
3208 # move mis-sorted standard packages in debuginfo folders into standard folders.
3209 # If duplicates already exists in standard folder: overwrite if the other is newer, otherwise move the other one to the REMOVED folder
3210 if [[ -n "$(find ${LOCALREPO_DIR}/{built,downloaded}/debuginfo/*/packages -type f -name "*.rpm" | grep -v -E '^.*\/[^\/]*-debug(source|info)-[^\/]*$')" ]]; then
3211
3212 eval $(find ${LOCALREPO_DIR}/{built,downloaded}/debuginfo/*/packages -type f -name "*.rpm" | grep -v -E '^.*\/[^\/]*-debug(source|info)-[^\/]*$' | sed -E s/'^(.*)\/(built|downloaded)\/debuginfo\/(.*)$'/'\\mv -u "\1\/\2\/debuginfo\/\3" "\1\/\2\/\3\";'/)
3213 eval $(find ${LOCALREPO_DIR}/{built,downloaded}/debuginfo/*/packages -type f -name "*.rpm" | grep -v -E '^.*\/[^\/]*-debug(source|info)-[^\/]*$' | sed -E s/'^(.*)\/(built|downloaded)\/debuginfo\/(.*)$'/'\\mv -f "\1\/\2\/debuginfo\/\3" "\1\/\.REMOVED\/\2";'/)
3214
3215 fi
3216
3217}
3218
3219
3220localrepo_setupFedoraComps() {
3221
3222 # define local repo path
3223 localrepo_setEnvVars
3224
3225 local fedoraCompsBasePath=""
3226 local dirOrig=""
3227
3228 if ! ( [[ -n $(rpm -qa | grep 'intltool') ]] || sudo dnf install intltool -y || sudo dnf install intltool -y --enablerepo=[a-zA-Z0-9]* ); then
3229 echo -e "\nUnable to install intltools, which is required to [re]make 'fedora-comps'. 'fedora-comps' will not be [re]made. \nTo automatically [re]make fedora-comps, manually install the 'intltool' package and then re-run 'localrepo_setupFedoraComps' \n"
3230 return
3231 fi
3232
3233 echo "Fedora-comps will now be [re]made"
3234
3235 dirOrig="$(pwd)"
3236
3237 [[ -n "${FEDORA_COMPS_FILE_PATH}" ]] && fedoraCompsBasePath="${FEDORA_COMPS_FILE_PATH%/fedora-comps/*}" || fedoraCompsBasePath="${LOCALREPO_DIR%/}" && FEDORA_COMPS_FILE_PATH="${fedoraCompsBasePath}/fedora-comps/comps-f$(uname -r | sed -E s/'^.*\.fc([0-9]*)\..*$'/'\1'/).xml" && export FEDORA_COMPS_FILE_PATH
3238
3239 cd "${fedoraCompsBasePath}"
3240
3241 [[ -d "${fedoraCompsBasePath}/fedora-comps" ]] && [[ -f "${fedoraCompsBasePath}/fedora-comps/Makefile" ]] && cd "${fedoraCompsBasePath}/fedora-comps" && make clean || ( [[ -d "${fedoraCompsBasePath}/fedora-comps" ]] && \mv -f "${fedoraCompsBasePath}/fedora-comps" "${fedoraCompsBasePath}/fedora-comps.old" ) && git clone 'http://git@pagure.io/fedora-comps.git' && cd "${fedoraCompsBasePath}/fedora-comps"
3242
3243 make all && make validate
3244
3245 chmod -R 775 "${fedoraCompsBasePath}/fedora-comps"
3246 chown -R root:wheel "${fedoraCompsBasePath}/fedora-comps"
3247
3248 cd "${dirOrig}"
3249
3250}
3251
3252
3253localrepo_repoBackup() {
3254 # backs up the local repo using rsync if either:
3255 # a) LOCALREPO_BACKUP_DIR is defined and not equal to the string "NONE"(this is the priority)
3256 # b) /DATA/${LOCALREPO_DIR#/} exists (to not use this by default, define and export LOCALREPO_BACKUP_DIR)
3257 #
3258 # To not backup the repo ever (including not using /DATA/${LOCALREPO_DIR#/}, even if it exists), define/export LOCALREPO_BACKUP_DIR="NONE"
3259
3260 # see if "${LOCALREPO_BACKUP_DIR} or "/DATA/${LOCALREPO_DIR#/}" exists
3261 localrepo_setEnvVars
3262
3263 # If we have a backup location, run rsync to updaate the repo
3264 if [[ -n "${LOCALREPO_BACKUP_DIR}" ]] && [[ "${LOCALREPO_BACKUP_DIR}" != "NONE" ]]; then
3265
3266 [[ -d "${LOCALREPO_BACKUP_DIR}" ]] || mkdir --parents "${LOCALREPO_BACKUP_DIR}"
3267
3268 rsync -avP ${LOCALREPO_DIR}/* "${LOCALREPO_BACKUP_DIR}"
3269
3270 fi
3271
3272}
3273
3274localrepo_cleanDatabase() {
3275 # deletes all repo data (NOT packages, just the stuff createrepo generates)
3276 # use this to refresh the repo and regenerate all the repo data from scratch
3277
3278 echo "local repository database cleaning will begin in 5 seconds..." && sleep 5
3279
3280 dnf clean all
3281
3282 # define local repo path and list valid architectures
3283 localrepo_setEnvVars
3284
3285 local globstarState=""
3286 globstarState="$(shopt globstar)"
3287 globstarState="${globstarState##* }"
3288
3289 [[ "${globstarState}" == "off" ]] && shopt -s globstar
3290
3291 # clean repodata
3292
3293 chmod 777 ${LOCALREPO_DIR:?}/**/.repodata ${LOCALREPO_DIR:?}/.repodata ${LOCALREPO_DIR:?}/**/repodata ${LOCALREPO_DIR:?}/repodata ${LOCALREPO_DIR:?}/**/drpms ${LOCALREPO_DIR:?}/drpms ${LOCALREPO_DIR:?}/**/cache ${LOCALREPO_DIR:?}/cache
3294
3295 \rm -rf ${LOCALREPO_DIR:?}/**/.repodata ${LOCALREPO_DIR:?}/.repodata ${LOCALREPO_DIR:?}/**/repodata ${LOCALREPO_DIR:?}/repodata ${LOCALREPO_DIR:?}/**/drpms ${LOCALREPO_DIR:?}/drpms ${LOCALREPO_DIR:?}/**/cache ${LOCALREPO_DIR:?}/cache
3296
3297 [[ "${globstarState}" == "off" ]] && shopt -u globstar
3298
3299 # remake repo files
3300 localrepo_setupDNF
3301
3302}
3303
3304
3305localrepo_updateDatabase() {
3306 # generates the file tree structure (if needed), adds + sorts new packages, and calls "create repo" on each sub-tree in the local repo
3307 # repos are generated with a cache and with delta-rpm info
3308 #
3309 # NOTE: you will need to manually
3310 #
3311 # note: repos are generated for each level in ${LOCALREPO_DIR}. The top level repo contains all packages from its subrepos. e.g.,
3312 # localrepo/repodata/repomd.xml has everything (top-level repo)
3313 # localrepo/built/repodata/repomd.xml has all built rpms (mid-level repo)
3314 # localrepo/built/x86_64/repodata/repomd.xml has all non-debuginfo/debugsource built rpms with x86_64 architecture packages (bottom-level repo)
3315
3316 # define local repo path and list valid architectures
3317 localrepo_setEnvVars
3318
3319 local -a vaArray
3320 [[ -n "${VALID_ARCH_LIST}" ]] && vaArray=(${VALID_ARCH_LIST}) || vaArray=($(echo "noarch"; uname -pmi | sed -zE s/' '/'\n'/g | sort -u; [[ "$(uname -pmi | sed -zE s/' '/'\n'/g | sort -u)" == "x86_64" ]] && echo "i686" ))
3321
3322 local fedoraCompsFileCmd=""
3323 local localrepoBaseName="${LOCALREPO_DIR##*/}"
3324
3325 [[ -f "${FEDORA_COMPS_FILE_PATH}" ]] && fedoraCompsFileCmd="-g ${FEDORA_COMPS_FILE_PATH} "
3326
3327 # ensure valid permissions
3328 [[ "${USER}" == "root" ]] && chown -R root:wheel ${LOCALREPO_DIR}/{source,built,downloaded} && chmod -R 775 ${LOCALREPO_DIR}/{source,built,downloaded}
3329
3330 # add + sort all new packages into the local repo
3331 [[ ${1,,} =~ ^-+c((lean)?((-?repo)?(-?data)?)?)? ]] && echo "cleaning RPM database..." && sleep 2 && localrepo_cleanDatabase
3332 localrepo_makeFileTree
3333 localrepo_importBuiltRPMs
3334 localrepo_downloadMissingRPMs
3335 localrepo_sortNewRPMs
3336 localrepo_fixSorting_debuginfo
3337
3338
3339 # make dnf cache directory (if needed)
3340 [[ -d "/var/cache/dnf/${localrepoBaseName}" ]] || mkdir --parents "/var/cache/dnf/${localrepoBaseName}"
3341
3342 # make sure we have the createrepo function
3343 [[ -z $(rpm -qa | grep 'createrepo') ]] && sudo dnf install createrepo_c -y
3344
3345 # make source repo
3346 createrepo_c --workers $((( $(nproc) / 2 ))) ${fedoraCompsFileCmd} -c "${LOCALREPO_DIR}/source/cache/" --deltas "${LOCALREPO_DIR}/source"
3347
3348 for ll in {built,downloaded,built/debuginfo,downloaded/debuginfo}; do
3349 for mm in "${vaArray[@]}"; do
3350 # make the bottom-level repos
3351 createrepo_c --workers $((( $(nproc) / 2 ))) ${fedoraCompsFileCmd} -c "${LOCALREPO_DIR}/${ll}/${mm}/cache/" --deltas "${LOCALREPO_DIR}/${ll}/${mm}/"
3352 done
3353
3354 # create repos for mid-level parent repos
3355 createrepo_c --workers $((( $(nproc) / 2 ))) ${fedoraCompsFileCmd} -c "${LOCALREPO_DIR}/${ll}/cache/" --deltas "${LOCALREPO_DIR}/${ll}"
3356
3357 done
3358
3359 # create main top-level parent repo
3360 #createrepo_c --workers $((( $(nproc) / 2 ))) ${fedoraCompsFileCmd} -c "${LOCALREPO_DIR}/cache/" $(eval echo $(ls -A1 ${LOCALREPO_DIR} | grep -v -E 'built|downloaded|source' | sed -E s/'^(.*)$'/'-x \$\(realpath \$\{LOCALREPO_DIR}\/\1\)'"'"'*'"'"''/)) --deltas "${LOCALREPO_DIR}"
3361
3362 createrepo_c --workers $((( $(nproc) / 2 ))) ${fedoraCompsFileCmd} -c "${LOCALREPO_DIR}/cache/" $(echo "$(find ${LOCALREPO_DIR} -maxdepth 1 -type d | grep -v -E '((built)|(downloaded)|(source)|(fedora-comps)|(drpms)|(repodata)|(cache)|(localmirror))' | sed -E s/'^'"$(srpmAutoBuild_escapeRegexChars "${LOCALREPO_DIR}")"'\/?(.*)$'/'\1'/ | grep -E '^.+$' | sed -E s/'^(.*)$'/'--excludes=\1\* '/)") --deltas "${LOCALREPO_DIR}"
3363
3364
3365
3366 # make symlinks to dnf cache directory
3367 ( [[ -d "/var/cache/dnf/${localrepoBaseName}/cache" ]] && echo "y" || echo "" ) | ln -s "${LOCALREPO_DIR}/cache/" "/var/cache/dnf/${localrepoBaseName}/cache"
3368 ( [[ -d "/var/cache/dnf/${localrepoBaseName}/repodata" ]] && echo "y" || echo "" ) | ln -s "${LOCALREPO_DIR}/repodata/" "/var/cache/dnf/${localrepoBaseName}/repodata"
3369
3370 sudo dnf --refresh --enablerepo=${localrepoBaseName}* makecache
3371
3372 localrepo_repoBackup
3373
3374}
3375
3376
3377localrepo_showFileTree() {
3378 # shows a generic filetree to screen showing the localrepo layout
3379 # note: this layout assumes x86_64. It is not dynamically generated. on other architectrures you will
3380 # have different options than "x86_64" and "i686", though the "noarch" option should apply to all.
3381
3382cat << EOF
3383|____localrepo
3384| |____{cache,repodata,drpms}
3385| |
3386| |
3387| |
3388| |____source
3389| | |____{cache,repodata,drpms}
3390| | |____packages
3391| | |____{0..9,a..z}
3392| |
3393| |
3394| |
3395| |____built
3396| | |____{cache,repodata,drpms}
3397| | |
3398| | |____x86_64
3399| | | |____{cache,repodata,drpms}
3400| | | |____packages
3401| | | |____{0..9,a..z}
3402| | |
3403| | |____noarch
3404| | | |____{cache,repodata,drpms}
3405| | | |____packages
3406| | | |____{0..9,a..z}
3407| | |
3408| | |___i686
3409| | | |____{cache,repodata,drpms}
3410| | | |____packages
3411| | | |____{0..9,a..z}
3412| | |
3413| | |____debuginfo
3414| | | |____{cache,repodata,drpms}
3415| | | |
3416| | | |____x86_64
3417| | | | |____{cache,repodata,drpms}
3418| | | | |____packages
3419| | | | |____{0..9,a..z}
3420| | | |
3421| | | |____noarch
3422| | | | |____{cache,repodata,drpms}
3423| | | | |____packages
3424| | | | |____{0..9,a..z}
3425| | | |
3426| | | |___i686
3427| | | | |____{cache,repodata,drpms}
3428| | | | |____packages
3429| | | | |____{0..9,a..z}
3430| |
3431| |
3432| |
3433| |____downloaded
3434| | |____{cache,repodata,drpms}
3435| | |
3436| | |____x86_64
3437| | | |____{cache,repodata,drpms}
3438| | | |____packages
3439| | | |____{0..9,a..z}
3440| | |
3441| | |____noarch
3442| | | |____{cache,repodata,drpms}
3443| | | |____packages
3444| | | |____{0..9,a..z}
3445| | |
3446| | |___i686
3447| | | |____{cache,repodata,drpms}
3448| | | |____packages
3449| | | |____{0..9,a..z}
3450| | |
3451| | |____debuginfo
3452| | | |____{cache,repodata,drpms}
3453| | | |
3454| | | |____x86_64
3455| | | | |____{cache,repodata,drpms}
3456| | | | |____packages
3457| | | | |____{0..9,a..z}
3458| | | |
3459| | | |____noarch
3460| | | | |____{cache,repodata,drpms}
3461| | | | |____packages
3462| | | | |____{0..9,a..z}
3463| | | |
3464| | | |___i686
3465| | | | |____{cache,repodata,drpms}
3466| | | | |____packages
3467| | | | |____{0..9,a..z}| |
3468EOF
3469
3470}
3471
3472localrepo_setupDNF() {
3473 # this will setup dnf to use the localrepo. All sub-repos will be added, though most are not initially enabled.
3474 # Note: someof the mirrors here probablyh wont work for local system access. You can remove the ones that dont work manually if your like
3475
3476 # define local repo path and list valid architectures
3477 localrepo_setEnvVars
3478
3479 local nameCur=""
3480 local nameCur2=""
3481 local enabledCur=""
3482 local skipCur=""
3483 local costCur=""
3484 local -a vaArray
3485
3486 [[ -n "${VALID_ARCH_LIST}" ]] && vaArray=(${VALID_ARCH_LIST}) || vaArray=($(echo "noarch"; uname -pmi | sed -zE s/' '/'\n'/g | sort -u; [[ "$(uname -pmi | sed -zE s/' '/'\n'/g | sort -u)" == "x86_64" ]] && echo "i686" ))
3487
3488 echo -n "Ensuring localrepo directory tree exists at ${LOCALREPO_DIR}..." >&2
3489 localrepo_makeFileTree
3490 echo "done"
3491
3492 if ( [[ -n $(rpm -qa | grep 'intltool') ]] || sudo dnf install intltool -y || sudo dnf install intltool -y --enablerepo=[a-zA-Z0-9]* ); then
3493 echo -n "Preparing to [re]make he fedora-comps files that provides group install info..." >&2
3494 localrepo_setupFedoraComps
3495 else
3496 echo -e "\nUnable to install intltools, which is required to [re]make 'fedora-comps'. 'fedora-comps' will not be [re]made. \nTo automatically [re]make fedora-comps, manually install the 'intltool' package and then run 'localrepo_setupFedoraComps' \n" >&2
3497 fi
3498
3499 echo "Beginning setup of the localrepo '*.repo' files and mirrorlists..." >&2
3500
3501 [[ -f "/etc/yum.repos.d/${LOCALREPO_DIR##*/}.repo" ]] && ( chmod 775 "/etc/yum.repos.d/${LOCALREPO_DIR##*/}.repo" || (( 1 == 1 )) ) && \mv -f "/etc/yum.repos.d/${LOCALREPO_DIR##*/}.repo" "/etc/yum.repos.d/${LOCALREPO_DIR##*/}.repo.old"
3502
3503 [[ -d "${LOCALREPO_DIR%/}/localmirror" ]] && ( [[ -d "${LOCALREPO_DIR%/}/localmirror/.old" ]] && \rm -rf "${LOCALREPO_DIR%/}/localmirror/.old" ) && mkdir "${LOCALREPO_DIR%/}/localmirror/.old" && \mv -f ${LOCALREPO_DIR%/}/localmirror/mirror-* "${LOCALREPO_DIR%/}/localmirror/.old" || mkdir --parents "${LOCALREPO_DIR%/}/localmirror"
3504
3505 [[ "${USER}" == "root" ]] && echo "$(echo "$(cat "/etc/dnf/dnf.conf" | grep -v -E '^fastestmirror=')" && echo "fastestmirror=true")" > "/etc/dnf/dnf.conf"
3506
3507############################################################
3508cat << EOF > "/etc/yum.repos.d/${LOCALREPO_DIR##*/}.repo"
3509[localrepo]
3510name=localrepo - Fedora \$releasever - ALL
3511mirrorlist=file://${LOCALREPO_DIR}/localmirror/mirror-localrepo-all
3512enabled=1
3513metadata_expire=1d
3514repo_gpgcheck=0
3515type=rpm
3516gpgcheck=0
3517gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-\$releasever-\$basearch
3518skip_if_unavailable=False
3519cost=20
3520
3521EOF
3522############################################################
3523
3524#setup mirrorlist for base localrepo. This is used as a template for the rest of the mirrorlists.
3525############################################################
3526cat << EOF > "${LOCALREPO_DIR}/localmirror/mirror-localrepo-all"
3527file:///${LOCALREPO_DIR#/}
3528localhost/${LOCALREPO_DIR#/}
3529localhost:22/${LOCALREPO_DIR#/}
3530localhost:80/${LOCALREPO_DIR#/}
3531localhost:8080/${LOCALREPO_DIR#/}
3532http://127.0.0.1/${LOCALREPO_DIR#/}
3533http://127.0.0.1:22/${LOCALREPO_DIR#/}
3534http://127.0.0.1:80/${LOCALREPO_DIR#/}
3535http://127.0.0.1:8080/${LOCALREPO_DIR#/}
3536https://127.0.0.1/${LOCALREPO_DIR#/}
3537https://127.0.0.1:22/${LOCALREPO_DIR#/}
3538https://127.0.0.1:80/${LOCALREPO_DIR#/}
3539https://127.0.0.1:8080/${LOCALREPO_DIR#/}
3540http://[::1]/${LOCALREPO_DIR#/}
3541http://[::1]:22/${LOCALREPO_DIR#/}
3542http://[::1]:80/${LOCALREPO_DIR#/}
3543http://[::1]:8080/${LOCALREPO_DIR#/}
3544https://[::1]/${LOCALREPO_DIR#/}
3545https://[::1]:22/${LOCALREPO_DIR#/}
3546https://[::1]:80/${LOCALREPO_DIR#/}
3547https://[::1]:8080/${LOCALREPO_DIR#/}
3548EOF
3549############################################################
3550
3551 # setup mirrorlists for "source" and "built" and "downloaded" + all sub-repos under "built" and "downloaded"
3552 for ll in {source,built,downloaded,built/debuginfo,downloaded/debuginfo}; do
3553
3554 for mm in {"","${vaArray[@]}"}; do
3555
3556 [[ "${ll}" == "source" ]] && [[ -n "${mm}" ]] && continue
3557
3558 nameCur="localrepo-${ll//'/'/'-'}"
3559 nameCur2="${ll^^}"
3560
3561 [[ -n ${mm} ]] && nameCur="${nameCur}-${mm}" && nameCur2="${nameCur2}-${mm}"
3562
3563 [[ -z ${mm} ]] && [[ ${ll} != */debuginfo ]] && enabledCur="1" || enabledCur="0"
3564
3565 ( [[ -z ${mm} ]] && [[ "${ll}" != "downloaded" ]] ) && skipCur="False" || skipCur="True"
3566
3567 costCur=0
3568 [[ "${ll}" == "downloaded" ]] && costCur=10
3569 [[ ${ll} == */debuginfo ]] && costCur=$((( $costCur + 2 )))
3570 [[ -z "${mm}" ]] || costCur=$((( $costCur + 1 )))
3571 if [[ -n "$(echo "${vaArray[@]}" | grep 'x86_64')" ]]; then
3572 [[ "${mm}" = "i686" ]] && costCur=$((( $costCur + 6 )))
3573 [[ "${mm}" = "noarch" ]] && costCur=$((( $costCur + 3 )))
3574 fi
3575
3576 [[ -f "${LOCALREPO_DIR}/localmirror/mirror-${nameCur}" ]] && chmod 775 "${LOCALREPO_DIR}/localmirror/mirror-${nameCur}" || touch "${LOCALREPO_DIR}/localmirror/mirror-${nameCur}"
3577 echo "$(cat "${LOCALREPO_DIR}/localmirror/mirror-localrepo-all" | sed -E s/'^(.*)$'/'\1\/'"${ll//'/'/'\/'}"'\/'"${mm}"/ | sed -E s/'^(.*)\/$'/'\1'/)" > "${LOCALREPO_DIR}/localmirror/mirror-${nameCur}"
3578
3579############################################################
3580cat << EOF >> "/etc/yum.repos.d/${LOCALREPO_DIR##*/}.repo"
3581[${nameCur}]
3582name=localrepo - Fedora \$releasever - ${nameCur2}
3583mirrorlist=file://${LOCALREPO_DIR}/localmirror/mirror-${nameCur}
3584enabled=${enabledCur}
3585metadata_expire=1d
3586repo_gpgcheck=0
3587type=rpm
3588gpgcheck=0
3589gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-\$releasever-\$basearch
3590skip_if_unavailable=${skipCur}
3591cost=${costCur}
3592
3593EOF
3594############################################################
3595
3596 done
3597
3598 done
3599
3600 chmod 775 "/etc/yum.repos.d/${LOCALREPO_DIR##*/}.repo"
3601 chmod -R 775 "${LOCALREPO_DIR}/localmirror"
3602
3603 sync
3604
3605 echo -e "\n*.repo files and local mirrorlists for ${LOCALREPO_NAME} have been generated! \nThe packages contained in ${LOCALREPO_NAME} should now be accessable via DNF. \n" >&2
3606
3607}
3608
3609
3610########################### EXTRA - FUNCTIONS TO SETUP UEFI-DIRECT BOOTING USING DRACUT ###########################
3611
3612#!/bin/bash
3613
3614UEFIDracutUpdate() {
3615 # MAIN FUNCTION TO CREATE / UPDATE BOOTABLE EFI FILES
3616 #
3617 # Inputs are kernel versions to update the bootable efi files for (same format as $(uname -r))
3618 # If no (non-flag) inputs, all kernel versions will be updated
3619 #
3620 # This can be called with no arguments and should** figure them all out for you using information from current mounts.
3621 # ** It works well for me, but has only tested on configurations ive had on my system. This means:
3622 #
3623 # FIlesystems: ext4 and ZFS (on root) have been tested. XFS will probably work too.
3624 # brtfs probably wont work without a little modification (though maybe it will, idk)
3625 #
3626 # GPU: tested with nvidia gpu using nvidia (not nouveau) drivers. integrated graphics probably works too.
3627 # no special cases have been setup for AMD gpus.
3628 #
3629 # Other: LUKS should be handled appropriately. LVM and DM/MD RAID support has not been explicitly added.
3630 #
3631 # Fedora 29 is the only Fedora version tested. I imagine it works with others, but idk for sure.
3632 #
3633 # Including files in the initramfs: 3 directories will be automatically added to the initramfs (if they exist and contain files):
3634 #
3635 # /etc/systemd/personal - this is intended to be used for custom systemd services.
3636 # *.service files in /etc/systemd/personal are included and installed. Files in the other 2 dirs are only included.
3637 #
3638 # /usr/local/bin/my-services - this is intended for files that support the custom systemd services
3639 #
3640 # /usr/local/bin/my-services - this is intended for general scripts, including functions you might find
3641 # useful should you end up in the dracut emergency shell for whatever reason.
3642 #
3643 # NOTE: because this sets up everything in the kernel commandline, the devices need not be listed in /etc/{fs,crypt}tab
3644 # if you do have them listed there is can, in some instances, lead to issues
3645 # # example: it might ask you a 2nd time for a password to decrypt an already-decrypted drive
3646 #
3647 # NOTE: unless you use either pf the flags '-na' or '--no-ask', you will be asked for
3648 # confirmation that the parameters it has determined automatically are correct.
3649 # if it is getting something wrong, it *should* accept any manual hardcoded entries of the following parameters:
3650 # ${luksUUID} ${bootDisk} ${rootDisk} ${rootFSType} ${rootFlags} ${usrDisk} ${usrFSType} ${usrFlags}
3651 #
3652 # IMPORTANT NOTE: the variable 'kernelCmdline_static' is for all the "extra" kernel command line parameters you want to add.
3653 # I left what Im using in there, as an example, though this wont be ideal for most systems. You should set this manually,
3654 # or remove it / comment it out it entirely if you arent sure how to set up.
3655 #
3656 # NOTE: these codes probably require root privileges to run, though doesnt call sudo in case someone without root access wants to try it.
3657 # I recommend, if possible, to run this as the root user (e.g., call 'su' then run it)
3658
3659 # set local variables
3660
3661 local rootDisk="";
3662 local bootDisk="";
3663 local luksUUID="";
3664 local rootFSType="";
3665 local rootFlags="";
3666 local userResponse="";
3667 local noAskFlag=0;
3668 local kernelCmdline_static="";
3669 local dracutArgsExtra=""
3670 local nn=""
3671 local usrDisk=""
3672 local usrFSType=""
3673 local usrFlags=""
3674 local usrMountFlag=0
3675 local kernelCmdline_spectreMeltdownMitigations=""
3676
3677 local useHardcodedZFSInfoFlag=1
3678 # disable selinux when running from a live os
3679 [[ -n "$(findmnt / | grep '/dev/mapper/live')" ]] && setenforce 0 && dnf upgrade -y *dracut* *systemd*
3680
3681 kernelCmdline_static='rd.driver.pre=tpm rd.timeout=60 rd.debug rd.locale.LANG=en_US.UTF-8 rd.udev.log-priority=info rd.lvm=0 rd.lvm.conf=0 rd.md=0 rd.md.conf=0 rd.dm=0 rd.dm.conf=0 systemd.unified_cgroup_hierarchy gpt intel_pstate=hwp_only zswap.enabled=1 zswap.compressor=lz4 transparent_hugepages=always panic=60 --install /bin/vim'
3682
3683 kernelCmdline_spectreMeltdownMitigations='spec_store_bypass_disable=prctl noibrs noibpb spectre_v2=auto pti=auto'
3684
3685 [[ ${*,,} =~ ^(.+\ )?-+no?-?a(sk)?(\ .+)?$ ]] && noAskFlag=1
3686
3687 mount "$(myFindEFIDev)" 2>&1 | grep -v 'already mounted' >&2
3688
3689 # set parameters for root /ot / usr / luks disk information
3690
3691 # example or manually set parameters. Note that the leading '[param]=' part is auto added, and doesnt need to be included (though can be)
3692
3693 if (( ${useHardcodedZFSInfoFlag} == 1 )); then
3694 rootDisk='ZFS=FEDORA/ROOT'
3695 rootFSType='zfs'
3696 rootFlags='zfsutil,rw,relatime,seclabel,xattr,posixacl'
3697 luksUUID="luks-$(cryptsetup luksUUID /dev/disk/by-id/nvme-Samsung_SSD_970_PRO_1TB_S462NF0K403461K-part2)"
3698 bootDisk='/dev/disk/by-id/nvme-Samsung_SSD_970_PRO_1TB_S462NF0K403461K-part1'
3699 usrDisk='ZFS=FEDORA/ROOT/USR'
3700 usrFSType='zfs'
3701 usrFlags='zfsutil,rw,relatime,seclabel,xattr,posixacl'
3702 fi
3703
3704 #rootDisk="/dev/mapper/luks-$(cryptsetup luksUUID /dev/disk/by-id/nvme-INTEL_MEMPEK1W032GA_PHBT814600LW032E-part5)"
3705 #bootDisk='/dev/disk/by-id/nvme-INTEL_MEMPEK1W032GA_PHBT814600LW032E-part3'
3706 #luksUUID="luks-$(cryptsetup luksUUID /dev/disk/by-id/nvme-INTEL_MEMPEK1W032GA_PHBT814600LW032E-part5)"
3707 #rootFSTye='ext4'
3708 #rootFlags='rw,relatime'
3709
3710 # automatically find parameters for root, boot and luks if they are empty (i.e., not hard-coded)
3711
3712 [[ -z "${rootDisk}" ]] && [[ -n "$(mount -l | grep 'on / type' | sed -E s/'^(.*) on \/ type .*$'/'\1'/)" ]] && rootDisk="$(mount -l | grep 'on / type' | sed -E s/'^(.*) on \/ type .*$'/'\1'/)";
3713
3714 [[ -z "${bootDisk}" ]] && bootDisk="$(myFindEFIDev)"
3715
3716 [[ -z "${luksUUID}" ]] && luksUUID="$(myDevToID -u "$(echo "$(for nn in /dev/mapper/*; do [[ $(cryptsetup status "$nn" 2>&1) != *"not found" ]] && cryptsetup status "$nn" 2>/dev/null; done)" | grep 'device: ' | sed -E s/'^.*(\/dev\/.*)$'/'\1'/)" | sed -E s/'^UUID='/'luks-'/ | grep -vE '^luks-$')" && luksUUID="$(echo "${luksUUID}" | while read -r nn; do [[ -n "$(dmsetup table "${nn}" | grep 'logon')" ]] && echo "${nn}"; done)"
3717 #(( $(echo -n "${luksUUID}" | wc -l) > 1 )) && luksUUID="$(for nn in ${luksUUID}; do [[ -n "$(dmsetup table "${nn}" 2>/dev/null | grep 'logon')" ]] && echo "${nn}"; done)"
3718
3719 [[ -z "${rootFSType}" ]] && [[ -n "$(mount -l | grep 'on / type' | sed -E s/'^.* on \/ type ([^ ]*) .*$'/'\1'/)" ]] && rootFSType="$(mount -l | grep 'on / type' | sed -E s/'^.* on \/ type ([^ ]*) .*$'/'\1'/)";
3720 [[ "${rootDisk}" == "ZFS="* ]] && rootFSType='zfs'
3721 [[ ${rootFSType#*=} =~ ^[Zz][Ff][Ss]$ ]] && rootFSype="zfs" && [[ -n "${rootDisk}" ]] && rootDisk="ZFS=$(echo "${rootDisk}" | sed -E s/'^[Zz][Ff][Ss]=(.*)'/'\1'/)"
3722
3723 [[ -z "${rootFlags}" ]] && [[ -n "$(mount -l | grep 'on / type' | sed -E s/'^.* on \/ type [^ ]* \(([^\)]*)\).*$'/'\1'/)" ]] && rootFlags="$(mount -l | grep 'on / type' | sed -E s/'^.* on \/ type [^ ]* \(([^\)]*)\).*$'/'\1'/)";
3724 [[ ${rootFSType#*=} =~ ^[Zz][Ff][Ss]$ ]] && [[ ! ${rootFlags#'rootFlags='} =~ ^(.+,)?zfsutil(,.+)?$ ]] && rootFlags="zfsutil,${rootFlags#'rootFlags='}"
3725
3726 # add in leading '[param]='
3727
3728 [[ -n "${rootDisk}" ]] && rootDisk="root=$(myDevToID "${rootDisk#'root='}") rw";
3729 [[ -n "${bootDisk}" ]] && bootDisk="boot=$(myDevToID "${bootDisk#'boot='}")";
3730 [[ -n "${luksUUID}" ]] && luksUUID="${luksUUID,,}" && luksUUID="${luksUUID#'*luks.uuid='}" && luksUUID="luks-${luksUUID#'luks-'}" && luksUUID="rd.luks.uuid=${luksUUID#'*luks.uuid='}";
3731 [[ -n "${rootFSType}" ]] && rootFSType="rootfstype=${rootFSType#'rootfstype='}";
3732 [[ -n "${rootFlags}" ]] && rootFlags="rootflags=${rootFlags#'rootflags='}";
3733
3734 # same steps as above, but for a separate /usr mount (if it exists)
3735
3736 ( [[ -n "$(cat /etc/mtab | grep ' /usr ')" ]] || [[ -n "${usrDisk}${usrFSType}${usrFlags}" ]] ) && usrMountFlag=1
3737
3738 if (( $usrMountFlag == 1 )); then
3739
3740 [[ -z "${usrDisk}" ]] && [[ -n "$(mount -l | grep 'on /usr type' | sed -E s/'^(.*) on \/usr type .*$'/'\1'/)" ]] && usrDisk="$(mount -l | grep 'on /usr type' | sed -E s/'^(.*) on \/usr type .*$'/'\1'/)";
3741
3742 [[ -z "${usrFSType}" ]] && [[ -n "$(mount -l | grep 'on /usr type' | sed -E s/'^.* on \/usr type ([^ ]*) .*$'/'\1'/)" ]] && usrFSType="$(mount -l | grep 'on /usr type' | sed -E s/'^.* on \/usr type ([^ ]*) .*$'/'\1'/)";
3743 [[ "${usrDisk}" == 'ZFS='* ]] && usrFSType='zfs'
3744 [[ ${usrFSType#*=} =~ ^[Zz][Ff][Ss]$ ]] && usrFSype="zfs" && [[ -n "${usrDisk}" ]] && usrDisk="ZFS=$(echo "${usrDisk}" | sed -E s/'^[Zz][Ff][Ss]=(.*)'/'\1'/)"
3745
3746 [[ -z "${usrFlags}" ]] && [[ -n "$(mount -l | grep 'on /usr type' | sed -E s/'^.* on \/usr type [^ ]* \(([^\)]*)\).*$'/'\1'/)" ]] && usrFlags="$(mount -l | grep 'on /usr type' | sed -E s/'^.* on \/usr type [^ ]* \(([^\)]*)\).*$'/'\1'/)";
3747 [[ ${usrFSType#*=} =~ ^[Zz][Ff][Ss]$ ]] && [[ ! ${usrFlags#'mount.usrflags='} =~ ^(.+,)?zfsutil(,.+)?$ ]] && usrFlags="zfsutil,${usrFlags#'mount.usrflags='}"
3748
3749 [[ -n "${usrDisk}" ]] && usrDisk="mount.usr=$(myDevToID "${usrDisk#'mount.usr='}")";
3750 [[ -n "${usrFSType}" ]] && usrFSType="mount.usrfstype=${usrFSType#'mount.usrfstype='}";
3751 [[ -n "${usrFlags}" ]] && usrFlags="mount.usrflags=${usrFlags#'mount.usrflags='}";
3752 fi
3753
3754 # automatically make additions to the command line that are specific to using a nvidia gpu, using LUKS, and using ZFS
3755
3756 [[ -n "$(rpm -qa | grep 'nvidia')" ]] && kernelCmdline_static="${kernelCmdline_static} rd.driver.blacklist=nouveau rd.modprobe.blacklist=nouveau rd.driver.pre=nvidia rd.driver.pre=nvidia_uvm rd.driver.pre=nvidia_drm rd.driver.pre=drm nvidia-dvm.modeset=1"
3757 [[ -n "${luksUUID}" ]] && kernelCmdline_static="${kernelCmdline_static} rd.driver.pre=dm_crypt rd.luks.allow-discards rd.luks.timeout=60"
3758 [[ -n "$(rpm -qa | grep 'zfs')" ]] && kernelCmdline_static="${kernelCmdline_static} zfs.zfs_flags=0x1D8 zfs_ignorecache=1"
3759 [[ ${rootFSType#*=} =~ ^[Zz][Ff][Ss]$ ]] && kernelCmdline_static="${kernelCmdline_static} rd.driver.pre=zfs zfs_force=1"
3760
3761 kernelCmdline_systemdUnits='systemd.show_status'
3762# for nn in /etc/systemd/personal/*.service; do
3763# [[ "${nn##*/}" != 'my-zfs-'* ]] && kernelCmdline_systemdUnits="${kernelCmdline_systemdUnits} "'rd.systemd.mask="'"${nn##*/}"'"'
3764# done
3765 [[ -f "/etc/systemd/personal/zfsSwitchServices.sh" ]] && kernelCmdline_systemdUnits="${kernelCmdline_systemdUnits} "'rd.systemd.run="/bin/chmod 777 /etc/systemd/personal/zfsSwitchServices.sh" systemd.run="/bin/bash -c '"'"'/etc/systemd/personal/zfsSwitchServices.sh'"'"'"'
3766 # systemd.run_success_action=none systemd.run_failure_action=none'
3767 #[[ ${rootFSType#*=} =~ ^[Zz][Ff][Ss]$ ]] && kernelCmdline_systemdUnits="${kernelCmdline_systemdUnits} "'rd.systemd.units="my-zfs-import.service" rd.systemd.units="my-zfs-mount.service"'
3768
3769 #if [[ ${rootFSType#*=} =~ ^[Zz][Ff][Ss]$ ]]; then
3770 #...
3771 #else
3772 # for nn in /etc/systemd/personal/*.service; do
3773 # [[ ${nn} =~ ^my-zfs-.*\.service$ ]]] && kernelCmdline_systemdUnits='${kernelCmdline_systemdUnits} systemd.mask="'"${nn##*/}"'"'
3774 # done
3775 #fi
3776
3777 kernelCmdline="${luksUUID} ${bootDisk} ${rootDisk} ${rootFSType} ${rootFlags} ${usrDisk} ${usrFSType} ${usrFlags} ${kernelCmdline_spectreMeltdownMitigations} ${kernelCmdline_systemdUnits} ${kernelCmdline_static} rd.info rd.shell rd.driver.pre=vfat rhgb";
3778 kernelCmdline="$(echo "${kernelCmdline}" | sed -E s/'^[ \t]*([^ \t].*[^ \t])[ \t]*$'/'\1'/ | sed -E s/'[ \t]+'/' '/g)";
3779
3780 # Setup additional (non-kernel-commandline) dracut arguments.
3781 # You may want to customize the initial 'dracutArgsExtra' variable, though this isnt as important as custom setting 'kernelCmdline_static' is
3782
3783 dracutArgsExtra='--early-microcode --nohardlink'
3784
3785 # include items from /usr/local/my-{scripts,services}
3786 for nn in '/etc/systemd/personal/' /usr/local/bin/my-{scripts,services}/ /usr/local/bin/my-{scripts,services}/*.sh /etc/systemd/personal/*{.sh,.service}; do
3787 dracutArgsExtra="${dracutArgsExtra} --include ${nn} ${nn}"
3788 done
3789
3790 # include + install items from /etc/systemd/personal into both /etc/systemd/personal and /etc/systemd/system in the initrd
3791 if [[ -d "/etc/systemd/personal" ]]; then
3792 for nn in /etc/systemd/personal/*{.sh,.service}; do
3793 [[ "${nn}" == *.service ]] && chmod -x "${nn}" || chmod +x "${nn}"
3794 \cp -f "${nn}" "/usr/lib/systemd/system/";
3795
3796 dracutArgsExtra="${dracutArgsExtra} --include ${nn} ${nn//\/personal\//\/system\/}";
3797 dracutArgsExtra="${dracutArgsExtra} --include ${nn} ${nn//\/personal\//\/user\/}";
3798
3799 dracutArgsExtra="${dracutArgsExtra} --install ${nn}";
3800 [[ -e "${nn//\/personal\//\/system\/}" ]] && dracutArgsExtra="${dracutArgsExtra} --install ${nn//\/personal\//\/system\/}";
3801 [[ -e "${nn//\/personal\//\/user\/}" ]] && dracutArgsExtra="${dracutArgsExtra} --install ${nn//\/personal\//\/user\/}";
3802 done
3803 fi
3804
3805 # manually specify boot stub location
3806 [[ -e "/usr/lib/systemd/boot/efi/linuxx64.efi.stub" ]] && dracutArgsExtra="${dracutArgsExtra} --uefi-stub /usr/lib/systemd/boot/efi/linuxx64.efi.stub"
3807
3808 # Print info to screen about the parsed parameters.
3809 # If '--no-ask' flag is set, pause for 10 seconds then continue.
3810 # Otherwise, pause for a minute and request user feedback.
3811 # Note: if no feedbback is received in 1 minute, the code will continue running.
3812
3813 echo -e "\n\nTHE FOLLOWING SETTINGS HAVE BEEN DYNAMICALLY SET (UNLESS OVERWRITTEN BY HARD-CODED DEFAULTS) \n"
3814 (( $noAskFlag == 0 )) && echo -e "Do these look correct? \n----> An empty/null response or a response of y[es] will be taken as \"yes\" \n----> Any other non-empty response will be taken as \"no\" \n----> Timeout is 60 seconds. Default response upon timeout is \"yes\" \n"
3815 echo -e " ${rootDisk} $( [[ -n "${rootDisk}" ]] && echo '\n ' )${rootFSType}$( [[ -n "${rootFSType}" ]] && echo '\n ' )${rootFlags}$( [[ -n "${rootFlags}" ]] && echo '\n ' )${bootDisk}$( [[ -n "${bootDisk}" ]] && echo '\n ' )${luksUUID}$( [[ -n "${luksUUID}" ]] && echo '\n ' )${usrDisk}$( [[ -n "${usrDisk}" ]] && echo '\n ' )${usrFSType}$( [[ -n "${usrFSType}" ]] && echo '\n ' )${usrFlags}$( [[ -n "${usrFlags}" ]] && echo '\n' ) \nAdditional Dracut parameters: -fvM --uefi ${dracutArgsExtra} \n\nFULL KERNEL COMMAND LINE: \n\n${kernelCmdline} \n";
3816
3817 (( $noAskFlag == 0 )) && read -iE -t 60 -p "Response ( <null>/y[es] --> yes | anything else --> no ): " userResponse && [[ -n "${userResponse}" ]] && [[ ! ${userResponse,,} =~ ^y(es)?$ ]] && [[ ! ${userResponse} =~ ^[\ \t]*$ ]] && return 1;
3818 (( $noAskFlag == 1 )) && echo "The code will proceed in 10 seconds..." && sleep 10;
3819
3820 # ensure a few extra modules have prerequisites met
3821
3822 [[ -n "$(for nn in {biosdevname,nbd,gpg,clevis,stratis,busybox,udisks2-iscsi}; do [[ -n "$(rpm -qa | grep "$nn")" ]] || echo '1'; done)" ]] && dnf install -y biosdevname nbd gpg *clevis* stratis* busybox udisks2-iscsi
3823
3824 # shift efi files and ensure systemd is up to date systemd
3825
3826 UEFIBootUpdate --shift-efi;
3827 systemctl set-default graphical.target --global --user;
3828 systemctl set-default graphical.target --global --system;
3829 systemctl daemon-reload --global --user;
3830 systemctl daemon-reload --global --system;
3831 systemctl daemon-reexec --global --system;
3832
3833 # run dracut --uefi, either for specific kernels or for all kernels
3834
3835 if (( $# == 0 )) || [[ ${*,,} =~ ^(.+\ )?-+a(ll)?(\ .+)?$ ]]; then
3836 dracut -fvM --uefi --kernel-cmdline "${kernelCmdline}" --regenerate-all ${dracutArgsExtra};
3837 else
3838 for nn in "${@}"; do
3839 [[ -e "/lib/modules/${nn}" ]] && dracut -fvM --uefi --kernel-cmdline "${kernelCmdline}" --kver "${nn}" ${dracutArgsExtra};
3840 done;
3841 fi;
3842
3843 UEFIBootUpdate
3844}
3845
3846
3847myFindEFIDev() {
3848 # attempts to automatically find the block device the system EFI partition is on
3849 # scans /etc/fstab and /etc/mtab for any vfat filesystem mounts on /boot, /boot/efi, or /efi
3850
3851 local -a EFIdev
3852 local nn=0
3853
3854 EFIdev=($(echo "$(cat /etc/{m,fs}tab | grep -E '[ \t](((\/[Bb][Oo][Oo][Tt])?\/[Ee][Ff][Ii])|\/[Bb][Oo][Oo][Tt])[ \t]' | sed -E s/'^[ \t]*([^ \t]*)[ \t].*$'/'\1'/)"))
3855
3856 for nn in $(seq 0 $((( ${#EFIdev[@]} - 1 )))); do
3857
3858 [[ ${EFIdev[$nn]^^} =~ ^UUID=[0-9A-Z-]+$ ]] && EFIdev[$nn]="$(findmnt ${EFIdev[$nn]} | tail -n $((( $(findmnt ${EFIdev[$nn]} | wc -l) - 1 ))) | grep -E '(((\/[Bb][Oo][Oo][Tt])?\/[Ee][Ff][Ii])|\/[Bb][Oo][Oo][Tt])[ \t]' | sed -E s/'^[^ \t]+[ \t]+([^ \t]*)[ \t].*$'/'\1'/)"
3859
3860 [[ ${EFIdev[$nn]} =~ ^\/dev\/disk\/by-id\/.+$ ]] && EFIdev[$nn]="$(echo "/dev/$(ls -l1 /dev/disk/by-id | grep -F "/${1##*/}" | head -n 1 | sed -E s/'^.* -> \.\.\/\.\.\/(.*)$'/'\1'/)")"
3861
3862 done
3863
3864 echo "$(local nn=""; for nn in "${EFIdev[@]}"; do [[ -n "$(findmnt "${nn}" | grep 'vfat' | grep -E '^\/boot(\/efi)?[ \t]')" ]] && echo "${nn}"; done)" | sort -u
3865}
3866
3867myDevToID() {
3868 # find a unique block device name from /dev/disk/by-id or a unique uuid for the device
3869 # input is block device ( /dev/<...> )
3870 # output is the (full path of the) matching entry in /dev/disk/by-id/<...>, UNLESS using uuid flag
3871 # if flag '-u' or '--uuid' is used as 1st input, output will instead be 'UUID=<deviceUUID>'
3872 # if flag --type=<...> is used, where <...>=[by-]{partuuid,partlabel,path,id,label,uuid}; then the corresponding folder in /dec/disk will be used. Note that using 'uuid' here outputs the path in /dev/disk/uuid, NOT 'UUID=<deviceUUID>'
3873
3874 local uuidFlag=0
3875 local matchType=""
3876 local -a inAll0
3877 local inAll=""
3878 local nn=""
3879
3880 inAll0=("${@}")
3881
3882 for nn in $(seq 0 $((( ${#inAll0[@]} - 1 )))); do
3883
3884 if [[ ${inAll0[$nn],,} =~ ^-+u(uid)?$ ]]; then
3885 uuidFlag=1 && matchType='uuid' && inAll0[$nn]=""
3886
3887 elif [[ ${inAll0[$nn],,} =~ ^-+type=(by-)?(id|uuid|partuuid|partlabel|label|path)$ ]]; then
3888 [[ "${matchType}" != 'uuid' ]] && matchType="$(echo "${inAll0[$nn],,}" | sed -E s/'^-+type=["'"'"']?(by-)?(id|uuid|partuuid|partlabel|label|path)["'"'"']?$'/'\2'/)" && inAll0[$nn]=""
3889
3890 else
3891 inAll="$(cat <(echo "${inAll}") <(echo "${inAll0[$nn]}"))"
3892 fi
3893 done
3894
3895 inAll="$(echo "${inAll}" | grep -vE '^$')"
3896
3897 [[ -z "${matchType}" ]] && matchType='id'
3898
3899 if (( $(echo "${inAll}" | wc -l) > 1 )); then
3900
3901 (( $uuidFlag == 1 )) && matchType='-u' || matchType='type=by-'"${matchType}"
3902
3903 echo "${inAll}" | while read -r nn; do
3904 [[ -n "${nn}" ]] && myDevToID ${matchType} "${nn}"
3905 done
3906
3907 else
3908
3909 [[ "${inAll}" == '/dev/mapper/'* ]] && echo "${*}" && return
3910
3911 [[ "${inAll^^}" =~ ^ZFS=.+$ ]] && echo "ZFS=${*##*=}" && return
3912
3913 (( $uuidFlag == 1 )) && [[ "${inAll}" == /dev/disk/by-uuid/* ]] && [[ -e "${inAll}" ]] && echo "UUID=${*##*/}" && return
3914 (( $uuidFlag == 0 )) && [[ "${inAll}" == /dev/disk/by-${matchType}/* ]] && [[ -e "${inAll}" ]] && echo "${inAll}" && return
3915
3916 (( $uuidFlag == 0 )) && [[ "${inAll}" == /dev/disk/* ]] && [[ ! "${inAll}" == /dev/disk/by-${matchType}/* ]] && inAll="$(realpath "${inAll%/*}/$(ls -l1 ${inAll%/*} | grep -vE '(^nvme-eui|^nvme-nvme|^wwn)' | grep -F "${inAll##*/}" | sed -E s/'^.* [^ ]* -> (.*)$'/'\1'/ | sort -u | head -n 1)")"
3917
3918 (( $uuidFlag == 1 )) && echo "UUID=$(ls -l1 /dev/disk/by-uuid | grep -F "/${inAll##*/}" | head -n 1 | sed -E s/'^.* ([^ ]*) -> .*$'/'\1'/)"
3919 (( $uuidFlag == 0 )) && echo "/dev/disk/by-${matchType}/$(ls -l1 /dev/disk/by-${matchType} | grep -v -E '(nvme\-eui|nvme\-nvme|wwn)' | grep -F "/${inAll##*/}" | head -n 1 | sed -E s/'^.* ([^ ]*) -> .*$'/'\1'/)"
3920
3921 fi
3922}
3923
3924UEFIBootUpdate() {
3925 # Generates new EFI boot menu entries for new .efi files detected in <EFI_DEV>/EFI/Linux/linux-*.efi
3926 #
3927 # NOTES: 1) Old entries are not auto deleted. YOull have to do this manually with efibootmgr
3928 # 2) It determines "new" entries mt matching the loader menu name and the efi filename.
3929 # If there are 2 efi files with the same loader name (perhaps on different disks),
3930 # it wont automatically recognize/create the 2nd one. Basically, ensure the names are unique.
3931 #
3932 # ALT BEHAVIOR: use flag '--shift-efi' to instead rotate the current efi files into "_OLD" versions.
3933 # existing "_OLD" versions will be overwritten. This by default gives 1 backup copy, though
3934 # manually setting a filename to "*_WORKING" is also accepted,
3935 #
3936 # 3 efi name types will be considered when determining whether to make a efi boot file:
3937 # the original dracut output, and names are parsed like so:
3938 #
3939 # linux-$(uname -r)[_OLD|_WORKING]-<machineID>.efi (examples below)
3940 #
3941 # linux-4.18.18-300.fc29.x86_64_OLD-48c20436d5fd44b485482ed7dbea0a3f.efi
3942 # linux-4.19.12-301.fc29.x86_64_WORKING-48c20436d5fd44b485482ed7dbea0a3f.efi
3943 # linux-4.19.15-300.fc29.x86_64-48c20436d5fd44b485482ed7dbea0a3f.efi
3944 #
3945 # ( NOTE: menu entries will be named using everything between the 2 '-' characters - e.g. '4.19.12-301.fc29.x86_64_WORKING')
3946 #
3947 # The standard names automatically replace the "_OLD" names before each every update, and thus are always remade
3948 # and the "WORKING" names are left as is, and if they dont exist the current efi file will be made into the "_WORKING" efi file
3949
3950 local nn=0;
3951 local EFIcurmenu="";
3952 local -a kverEFI;
3953 local EFIbasedir="";
3954 local EFIdev0="";
3955 local EFIdev="";
3956 local EFIpart="";
3957 local EFIpartuuid=""
3958 local kverEFI="";
3959 local kverEFItemp="";
3960 local kverEFIWorking="";
3961 local -a kverEFINew;
3962
3963 # find base dir for efi device. should be /boot, /boot/efi, or /efi, depending of the system setup
3964
3965 if (( $# > 0 )) && [[ -d "${1}" ]]; then
3966 EFIbasedir="${1}";
3967 else
3968 EFIbasedir="$(findmnt $(myFindEFIDev) | grep -E '(((\/[Bb][Oo][Oo][Tt])?\/[Ee][Ff][Ii])|\/[Bb][Oo][Oo][Tt])[ \t]' | sed -E s/'^([^ \t]*).*$'/'\1'/)"
3969 if [[ ! -d "${EFIbasedir}" ]]; then
3970 if [[ -d "/boot/efi/EFI" ]]; then
3971 EFIbasedir="/boot/efi";
3972 elif [[ -d "/boot/EFI" ]]; then
3973 EFIbasedir="/boot";
3974 elif [[ -d "/boot/efi" ]]; then
3975 EFIbasedir="/booti/efi";
3976 elif [[ -d "/EFI" ]]; then
3977 EFIIbasedir="/";
3978 elif [[ -d "/efi" ]]; then
3979 EFIbasedir="/efi";
3980 else
3981 EFIbasedir="/boot/efi";
3982 fi
3983 fi
3984 fi
3985
3986 # break into device + partition
3987
3988 #EFIdev="$(mount -l | grep -F "${EFIbasedir}" | sed -E s/'^([^ ]*) .*$'/'\1'/ | sort -u)";
3989 EFIdev0="$(myDevToID "$(myFindEFIDev)")"
3990 EFIpart="$(echo -n "${EFIdev0}" | sed -E s/'^.*[^0-9]([0-9]+)$'/'\1'/)";
3991 EFIdev="$(echo -n "${EFIdev0}" | sed -E s/'^(.*)-part[0-9]*$'/'\1'/)";
3992 EFIpartUUID="$(myDevToID --type=partuuid "${EFIdev0}")"
3993 EFIpartUUID="${EFIpartUUID#'/dev/disk/by-partuuid/'}"
3994
3995 [[ -n "$(echo "${EFIdev}" | grep 'nvme')" ]] && EFIdev="${EFIdev%p}";
3996
3997 echo -e "\nThe following properties have been identified for the EFI system partition: \n Mount Point: \t ${EFIbasedir} \n Device Name: \t ${EFIdev} \n Partition: \t ${EFIpart} \n";
3998 sleep 5;
3999
4000 # get list of current menu entries and kernel versions of items to add
4001
4002 EFIcurmenu="$(efibootmgr -v 2>&1)";
4003
4004 kverEFI="$(find "${EFIbasedir}/EFI/Linux/" -maxdepth 1 -type f -name "linux-*.efi" | sort -V)";
4005 kverEFI="$(echo "$kverEFI" | grep -F "$(uname -m)_OLD-"; echo "$kverEFI" | grep -F "$(uname -m)_WORKING-"; echo "$kverEFI" | grep -F "$(uname -m)-")"
4006
4007 # check if *_WORKING efi boot file exists, if not copy current efi boot file into *_WORKING efi boot file
4008
4009 echo "$kverEFI" | grep -v -E '_(OLD|WORKING)-' | sort -u | while read -r nn; do [[ ! -f "${nn//$(uname -m)/$(uname -m)_WORKING}" ]] && cp "${nn}" "${nn//$(uname -m)/$(uname -m)_WORKING}" && echo -e "\nSince no ${nn%$(uname -m)*}_WORKING efi file exists, \nthe current efi boot file ${nn%$(uname -m)*} has been saved as a working backup. \nNote that this is not auto updated - you will have to manually update this file from now on (should you want to). \n" >&2; done
4010
4011 # get updated list of current menu entries and kernel versions of items to add
4012
4013 kverEFI="$(find "${EFIbasedir}/EFI/Linux/" -maxdepth 1 -type f -name "linux-*.efi" | sort -V)";
4014 kverEFI="$(echo "$kverEFI" | grep -F "$(uname -m)_OLD-"; echo "$kverEFI" | grep -F "$(uname -m)_WORKING-"; echo "$kverEFI" | grep -F "$(uname -m)-")"
4015
4016 # update efi boot order or (if --shift-efi flag set) shift the on-disk efi files
4017
4018 [[ -n "${kverEFI}" ]] && echo "${kverEFI}" | while read -r nn; do
4019 if [[ ${1,,} =~ ^-+s(hift)?-?e(fi)?$ ]]; then
4020 \mv -f "$(echo -n "${nn}")" "$(echo -n "${nn%$(uname -m)*}$(uname -m)_OLD-${kverEFI[$nn]##*-}")";
4021 else
4022 kverEFItemp="${nn,,}"
4023 [[ -z "$(echo "${EFIcurmenu,,}" | grep -F "$(echo -n "${kverEFItemp##*linux-}")" | grep -vF "${EFIpartuuid}")" ]] && efibootmgr -c -d "${EFIdev}" -p ${EFIpart} -l "$(echo -n "${nn##"$EFIbasedir"}")" -L "Fedora-EFI_$(echo -n "${nn##*linux-}" | sed -E s/'^([^-]*-[^-]*)-.*$'/'\1'/)" 1>/dev/null;
4024 fi
4025 done
4026
4027
4028 # print new boot order (unless using --shift-efi)
4029 [[ ${1,,} =~ ^-+s(hift)?-?e(fi)?$ ]] || UEFIBootOrderList -v
4030}
4031
4032UEFIBootOrderList() {
4033 # prints a "nice" list of active and inactive boot entries. Basically, a poretty alternative to the output of efibootmgr
4034 #
4035 # FLAGS
4036 #
4037 # use flag '-v' or '--verbose' to give additional output (including info on what disk/partition/file the boot entry represents)
4038 #
4039 # use flag '-m' or '--mod[ify]' to reorder the default boot list order
4040 # This will cause the boot list to be displayed, after which you will be interactively asked to choose entries to:
4041 # a) deactivate b) send to the top of the active list
4042 #
4043 # use flag '-nd' or '--no-dedup' to NOT de-deplicate the boot order list.
4044 # The default behavior is to automatically "fix" the boot order by removing duplicate entries from the boot order list
4045 # Note: this is NOT reffering to duplicates of the actual efi entries returned by 'efibootmgr',
4046 # but rather to any repeated (HEX x4) values in the boot order listing that is set via 'efibootmgr -o'
4047
4048 local nn="";
4049 local EFImenu="";
4050 local -a bootOrderVal;
4051 local -a bootOrderIsActive;
4052 local -a bootOrderInd;
4053 local -a bootOrderReMap;
4054 local activeIndList=""
4055 local inactiveIndList=""
4056 local bootCurTemp=""
4057 local indCurTemp=""
4058 local kk=0;
4059 local kk1=0;
4060
4061 bootOrderInd=($(echo -n "$(efibootmgr | grep -E '^BootOrder\:' | sed -E s/'^BootOrder\: (.*)$'/'\1'/ | myuniq | sed -zE s/'\n'/' '/g)"));
4062 [[ ${*,,} =~ ^(.+ )?-+no?-?d(edup)?( .+)?$ ]] || efibootmgr -o $(echo ${bootOrderInd[@]} | sed -E s/' '/','/g) 2>&1 1>/dev/null
4063 EFImenu="$(efibootmgr $( [[ ${*,,} =~ ^(.+ )?-+v(erbose)?( .+)?$ ]] && echo '-v' ) | tail -n +4)";
4064
4065 kk=0
4066 for nn in "${bootOrderInd[@]}"; do
4067 bootCurTemp="$(echo "${EFImenu}" | grep --color=auto -E '^Boot'"${nn}"'[\* ] ')"
4068 bootOrderVal[$kk]="$(echo "${bootCurTemp}" | sed -E s/'^Boot[^\* ]*[\* ] (.*)$'/'\1'/)";
4069 [[ "${bootCurTemp%% *}" == *\* ]] && bootOrderIsActive[$kk]=1 && activeIndList="${activeIndList} ${kk}"
4070 [[ ! "${bootCurTemp%% *}" == *\* ]] && bootOrderIsActive[$kk]=0 && inactiveIndList="${inactiveIndList} ${kk}"
4071 ((kk++))
4072 done
4073
4074 echo -e "\n||----------------------------------------------------------||\n||-------------------- EFI BOOT ENTRIES --------------------||\n||----------------------------------------------------------||\n";
4075 echo -e "\n||------------------------- ACTIVE -------------------------||\n";
4076
4077 kk1=0
4078 for kk in ${activeIndList}; do
4079 echo "(${kk1}) ${bootOrderVal[$kk]}"
4080 bootOrderReMap[$kk1]=${kk}
4081 ((kk1++))
4082 done
4083
4084 echo -e "\n\nNOTE: The above list is ordered by boot priority. The 1st listing is the \"default\" boot entry. \n The default behavior is to try these in order until a valid/working boot image is found.";
4085
4086 echo -e "\n\n||------------------------ INACTIVE ------------------------||\n";
4087
4088 for kk in ${inactiveIndList}; do
4089 echo "(${kk1}) ${bootOrderVal[$kk]}"
4090 bootOrderReMap[$kk1]=${kk}
4091 ((kk1++))
4092 done;
4093 echo -e "\n\nNOTE: To activate/deactivate/reorder efi boot menu entries, run 'UEFIBootOrderList -m [-v]'\n\n"
4094
4095 if [[ ${*,,} =~ ^(.+ )?-+m(od(ify)?)?( .+)?$ ]]; then
4096 local userResponse=""
4097
4098 echo -e "\nRespond to the following questions with a {space,comma,newline}-seperated list of indicies from the above listing. \nThe index is the number shown in (#) at the start of each line. \nNote: Non-numeric characters (except for spaces, commas and newlines) will be filtered out of the response and ignored. \n\nTimeout is 30 seconds\n"
4099
4100 read -ie -t 30 -p "Select boot entries to deactivate: " userResponse
4101
4102 userResponse="$(echo "${userResponse}" | sed -E s/'[ \n]'/' '/g | sed -E s/'[^0-9 ]'//g | sed -E s/' +'/' '/g | sed -E s/'^ $'//)"
4103
4104 if [[ -n "${userResponse}" ]]; then
4105 for kk in ${userResponse}; do
4106 (( $kk < ${#bootOrderReMap[@]} )) && efibootmgr -A -b "${bootOrderInd[${bootOrderReMap[$kk]}]}" 2>&1 1>/dev/null
4107 done
4108 fi
4109
4110 userResponse=""
4111 read -ie -t 30 -p "Select boot entries to place at the top of the \"active\" list: " userResponse
4112
4113 userResponse="$(echo "${userResponse}" | sed -E s/'[ \n]'/' '/g | sed -E s/'[^0-9 ]'//g | sed -E s/' +'/' '/g | sed -E s/'^ $'//)"
4114
4115 if [[ -n "${userResponse}" ]]; then
4116 local bootOrderNew=""
4117 local -a bootOrderNewTemp
4118 bootOrderNewTemp=("${bootOrderInd[@]}")
4119 for kk in ${userResponse}; do
4120 if (( $kk < ${#bootOrderReMap[@]} )); then
4121 efibootmgr -a -b ${bootOrderInd[${bootOrderReMap[$kk]}]} #2>/dev/null
4122 bootOrderNew="${bootOrderNew} ${bootOrderInd[${bootOrderReMap[$kk]}]}"
4123 bootOrderNewTemp[${bootOrderReMap[$kk]}]=""
4124 fi
4125 done
4126
4127 bootOrderNew="$(echo "${bootOrderNew} ${bootOrderNewTemp[@]}" | sed -E s/'[ \t\n\,]+'/' '/g | sed -E s/'^ *([^ ].*[^ ]) *$'/'\1'/ | myuniq | sed -zE s/'\n'/','/g | sed -E s/'^(.*[^.]),*$'/'\1\n'/)"
4128 efibootmgr -o "${bootOrderNew%,}" #2>&1 1>/dev/null
4129 fi
4130
4131 echo -e "\n\n||----------------- NEW BOOT MENU ORDERING -----------------|| \n\n"
4132 UEFIBootOrderList $( [[ ${*,,} =~ ^(.+ )?-+v(erbose)?( .+)?$ ]] && echo '-v' )
4133 fi
4134}
4135
4136myuniq() {
4137 # returns unique elements in a list
4138 # replacement for 'uniq', which is straight broken on my system
4139 # input should be list separated by newlines/spaces/tabs/commas
4140 # output is newline-separated list
4141
4142 local inAll=""
4143 local outAll=""
4144
4145 (( $# > 0 )) && inAll="${@}" || inAll="$(cat <&0)"
4146 inAll="$(echo -n "${inAll}" | sed -zE s/'[ ,\t]'/'\n'/g | sed -zE s/'\n+'/'\n'/g)"
4147 while [[ -n "${inAll}" ]]; do
4148 outAll="$(echo "${outAll}"; echo "${inAll}" | head -n 1)"
4149 inAll="$(echo -n "${inAll}" | grep -v -F "$(echo "${inAll}" | head -n 1)")"
4150 done
4151
4152 outAll="$(echo "${outAll}" | grep -E '.+')"
4153 echo "${outAll}"
4154}
4155
4156UEFIKernelPostInstallSetup() {
4157 # setup kernel post install script to automatically re-make the bootable efi files after a kernel update
4158 # untested, but i think it should work. Change '/usr/local/bin/my-scripts/dracut-UEFI-boot.sh' to wherever this file is actually saved.
4159
4160 cat << EOF > "/etc/kernel/postinst.d/dracut-EFI_postinst"
4161#!/bin/bash
4162
4163source /usr/local/bin/my-scripts/dracut-UEFI-boot.sh
4164
4165(( \$# > 0 )) && zfsDracutUpdate "\${@}" || zfsDracutUpdate
4166
4167[[ -d "/boot" ]] && [[ -n "\$(echo \$(rpm -qa | grep 'zfs'))" ]] && [[ -n "\$(zfs list | grep 'FEDORA/ROOT/BOOT')" ]] && zfsBackupBoot
4168
4169EOF
4170
4171 chmod 755 "/etc/kernel/postinst.d/dracut-EFI_postinst"
4172
4173}
4174
4175
4176myGetUserInput(){
4177 # this is intended as a user input request function, but apparently i never ended up using it....
4178
4179 local aCur=""
4180 local userResponse=""
4181 local aindSelect=0
4182 local -a arrayIn
4183 local kk=0
4184
4185 #readarray arrayIn < <(echo "${1}" | sort -u)
4186 echo "${1}" | sort -u | read -a arrayIn
4187
4188 if (( ${#arrayIn[@]} > 1 )); then
4189
4190 echo -e "\nUnable to determine the \"${2}\" device path. Please select one of the following. \nTimeout is 30 seconds, after which choice 0 will be used by default. \n\n"
4191
4192 kk=0
4193 for aCur in "${arrayIn[@]}"; do
4194 echo "(${kk}): ${aCur}"
4195 ((kk++))
4196 done
4197
4198 echo "(${kk}}: Manually enter boot device path"
4199 read -ie -t 30 -p "Choose a response [0-${kk}]: " userResponse
4200
4201 [[ ${userResponse} =~ ^[0-9]+$ ]] && (( $userResponse >= 0 )) && (( $userResponse <= $kk )) || userResponse=0
4202 (( $userResponse == $kk )) && read -ie -t 120 -p "Please enter the \"${2}\" device path: " aindSelect && [[ ! -e "${aindSelect}" ]] && echo "INPUT BLOCK DEVICE DOES NOT EXIST! THE CODE WILL NOW ABORT!" && exit 1
4203 (( $userResponse < $kk )) && aindSelect="${arrayIn[$userResponse]}"
4204
4205 echo "${userResponse}"
4206
4207 else
4208
4209 echo "${1}"
4210
4211 fi
4212}
4213
4214
4215# a few zfs-specific utility functions
4216
4217zfsBackupBoot() {
4218
4219 local -a fileChanged;
4220 local -a fileRemoved;
4221 local mountBOOTFlag=0;
4222 local nn="";
4223 local BOOTMountPoint=""
4224
4225 [[ -z "$(find /boot | grep -v -E '^\/boot$')" ]] && return
4226 [[ -z "$(find /BOOT | grep -v -E '^\/BOOT$')" ]] && mountBOOTFlag=1 && zfs mount FEDORA/ROOT/BOOT;
4227 BOOTMountPoint="$(zfs get mountpoint -r -t filesystem | grep -E 'mountpoint[ \t]+\/BOOT[ \t]' | sed -E s/'^([^ ]*) .*$'/'\1'/)"
4228 [[ -z "$(find ${BOOTMountPoint} | grep -v -E '^'"${BOOTMountPoint}"'$')" ]] && return
4229
4230 /bin/bash -c "mapfile -t fileChanged < <(rsync -avPAXEWH --super -n /boot/ ${BOOTMountPoint%/}/ | grep -v -E '\/$' | grep -v 'sending incremental file list');"
4231
4232 if (( ${#fileChanged[@]} > 0 )); then
4233 for nn in "${fileChanged[@]}"; do
4234 [[ -f "${BOOTMountPoint}/${nn}" ]] && mv -i -f "${BOOTMountPoint}/${nn}" "${BOOTMountPoint}/OLD/${nn}";
4235 done;
4236 fi;
4237
4238 rsync -aAXEPW --super /boot/ ${BOOTMountPoint}/;
4239
4240 /bin/bash -c "readarray fileRemoved < <(echo -n \"$(diff -dy --width=512 <(find \"${BOOTMountPoint}\" | sed -E s/'^'\"${BOOTMountPoint%/}\"'\/(.*)$'/'\1'/ | grep -v -E '^OLD' | sort -V) <(find \"/boot\" | sed -E s/'^\/boot\/(.*)$'/'\1'/ | sort -V))\" | grep '<' | sed -E s/'^(.+[^ \t])[ \t]*<.*$'/'\1'/);"
4241
4242 if (( ${#fileRemoved[@]} > 0 )); then
4243 for nn in "${fileRemoved[@]}";
4244 do
4245 [[ -d "${BOOTMountPoint}/OLD/$(echo -n "${nn%/*}/")" ]] || mkdir --parents "${BOOTMountPoint}/OLD/$(echo -n "${nn%/*}/")";
4246 mv -i -f "${BOOTMountPoint}/$(echo -n "${nn}")" "${BOOTMountPoint}/OLD/$(echo -n "${nn%/*}/")";
4247 done;
4248 fi;
4249
4250 (( ${mountBOOTFlag} == 1 )) && zfs umount FEDORA/ROOT/BOOT
4251
4252}
4253
4254zfsImportMountFEDORA() {
4255
4256 local nn=""
4257
4258 [[ ! -e "/etc/zfs/zpool.cache" ]] || rm -rf "/etc/zfs/zpool.cache"
4259
4260 [[ -n "$(/sbin/zpool list -H -o name | grep FEDORA)" ]] || /sbin/zpool import -N -o cachefile=none FEDORA || /sbin/zpool import -N -f -o cachefile=none FEDORA
4261 [[ -n "$(/sbin/zpool list -H -o name | grep DATA)" ]] || /sbin/zpool import -N -o cachefile=none DATA
4262 /sbin/zpool import -a -N -o cachefile=none
4263
4264 [[ -n "$(/sbin/zpool list -H -o name | grep FEDORA)" ]] && ( ( [[ -n "$(/sbin/zfs get -H -o value keylocation FEDORA/ROOT | grep "prompt")" ]] || /sbin/zfs set keylocation=prompt FEDORA/ROOT ) && ( [[ -n "$(/sbin/zfs get -H -o value canmount FEDORA/ROOT | grep "on")" ]] || /sbin/zfs set canmount=on FEDORA/ROOT ) && ( [[ -n "$(/sbin/zfs get -H -o value canmount FEDORA/KEYS | grep "noauto")" ]] || /sbin/zfs set canmount=noauto FEDORA/KEYS ) && /bin/systemctl set-environment BOOTFS=FEDORA/ROOT )
4265
4266 [[ -n "$(/sbin/zpool list -H -o name | grep FEDORA)" ]] && [[ "$(/sbin/zpool get -H -o value altroot FEDORA)" != "-" ]] && [[ "$(/sbin/zfs get -H -o value mounted FEDORA/ROOT)" != "yes" ]] && /sbin/zpool export FEDORA && ( /sbin/zpool import -N -o cachefile=none FEDORA || /sbin/zpool import -N -f -o cachefile=none FEDORA )
4267
4268 if [[ -n "$(/sbin/zpool list -H -o name | grep FEDORA)" ]]; then
4269 /sbin/zfs list -H -o name -r FEDORA/ROOT -t filesystem | while read -r nn; do
4270 mountCur="$(/sbin/zfs get -H -o value mountpoint "${nn}")"
4271 [[ ${mountCur} =~ ^\/sysroot.*$ ]] || /sbin/zfs set mountpoint="/sysroot/${mountCur#\/}" "${nn}"
4272 done
4273 fi
4274
4275 ( [[ -n "$(zpool list -H -o name | grep FEDORA)" ]] && [[ "$(/sbin/zfs get keystatus -H -o value FEDORA/ROOT)" == "unavailable" ]] ) && ( /bin/clevis decrypt < <( ( [[ "$(/sbin/zfs get mounted -H -o value FEDORA/KEYS)" == "yes" ]] || /sbin/zfs mount FEDORA/KEYS ) && cat "$(/sbin/zfs get mountpoint -H -o value FEDORA/KEYS)/secret.jwe" && /sbin/zfs umount FEDORA/KEYS && sleep 1 ) | /sbin/zfs load-key FEDORA/ROOT )
4276
4277 zfsFindMountOrder | while read -r nn; do /sbin/zfs mount -O "${nn}"; done
4278
4279}
4280
4281zfsFindMountOrder() {
4282
4283 local zfsList=""
4284 local zfsMount=""
4285 local zfsMount0=""
4286 local zfsMount1=""
4287 local zfsMountOrder=""
4288 local ROOT_DATASET=""
4289 local -a zfsMountSplitU
4290 local kk=0
4291 local nn=""
4292
4293 if (( $# > 1 )); then
4294 for nn in "${@}"; do zfsFindMountOrder "${nn}"; done && return
4295 elif (( $# > 0 )); then
4296 ROOT_DATASET="${*}"
4297 elif [[ -n "${root}" ]]; then
4298 ROOT_DATASET="$(echo "${root}" | sed -E s/'^[Zz][Ff][Ss][\=\:](.*)$'/'\1'/)"
4299 else
4300 ROOT_DATASET='FEDORA/ROOT'
4301 fi
4302
4303 zfsList="$(/sbin/zfs get -H -o name,value mountpoint -r "${ROOT_DATASET}" -t filesystem| grep -vE '(none$|legacy$)')"
4304 zfsMount="$(/sbin/zfs get -H -o value mountpoint -r "${ROOT_DATASET}" -t filesystem | grep -vE '(none$|legacy$)')"
4305 zfsMount0="${zfsMount}"
4306
4307 kk=0
4308 while [[ -n "${zfsMount0}" ]]; do
4309 zfsMountSplitU[$kk]="$(echo "${zfsMount0}" | sed -E s/'^(\/[^\/]*)\/?.*$'/'\1'/ | grep -vE '(none$|legacy$)' | sort -u)"
4310 ((kk++))
4311
4312 zfsMount0="$(echo "${zfsMount0}" | sed -E s/'^\/[^\/]*(\/?.*)$'/'\1'/ | grep -vE '(none$|legacy$)' | grep -E '^[^\ \t]+$')"
4313 done
4314
4315 zfsMount1="$( echo "${zfsMount}" | while read -r nn; do kk=0; echo -n "${nn}"; for kk in $( seq 0 $((( ${#zfsMountSplitU[@]} - $(echo "${nn}" | sed -E s/'[^\/]'//g | wc -m) ))) ); do echo -n '/.'; done; echo -ne "\n"; done )"
4316
4317 while [[ -n "${zfsMount1}" ]]; do
4318 zfsMountOrder="$(cat <(echo "${zfsMount1}" | grep -vE '\/\.$') <(echo "${zfsMountOrder}"))"
4319 zfsMount1="$(echo "${zfsMount1}" | grep -E '\/\.$' | sed -E s/'^(.*)\/\.$'/'\1'/)"
4320 done
4321
4322 echo "${zfsMountOrder}" | while read -r nn; do echo "${zfsList}" | grep -E "${nn//\//\\\/}"'$' | sed -E s/'^([^\t]*)\t.*$'/'\1'/; done
4323
4324}