project 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518
  1. #!/usr/bin/env bash
  2. # Copyright (C) 2016 Paul Kocialkowski <contact@paulk.fr>
  3. # Copyright (C) 2018 Andrew Robbins <contact@andrewrobbins.info>
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. PROJECT_ACTIONS_GENERIC=(usage dependencies download extract update build install release clean)
  18. PROJECT_ACTIONS_GENERIC_IGNORE_CHECK=(usage clean)
  19. PROJECT_ACTIONS_HELPERS=(arguments dependencies)
  20. INSTALL_REGEX='\([^:]*\):\(.*\)'
  21. project_include() {
  22. local project=$1
  23. local project_path=$(project_path "$project")
  24. unset -f "${PROJECT_ACTIONS[@]}"
  25. source "$project_path/$project"
  26. project_helper_include "$project"
  27. }
  28. project_helper_include() {
  29. local project=$1
  30. local project_path=$(project_path "$project")
  31. local include="$project_path/$project-helper"
  32. if [[ -f "$include" ]]
  33. then
  34. source "$include"
  35. fi
  36. }
  37. project_check() {
  38. local project="${1##*/}"
  39. local project_path="$(project_path "$project")"
  40. if ! [[ -f "$project_path/$project" ]]; then
  41. return 1
  42. fi
  43. }
  44. project_dependencies() {
  45. local project=$1
  46. shift
  47. local -a dependencies
  48. mapfile -t dependencies < <(project_file_contents_herit "$project" "$CONFIGS" "$DEPENDENCIES" "$@")
  49. if [[ -n ${dependencies[*]} ]]; then
  50. printf '%s\n' "${dependencies[@]}"
  51. fi
  52. }
  53. project_dependencies_check() {
  54. local project=$1
  55. shift
  56. local -a dependencies
  57. mapfile -t dependencies < <(project_dependencies "$project" "$@")
  58. local -i count=${#dependencies[@]}
  59. local -i missing=0
  60. for ((i = 0; i < count; i++)); do
  61. local -a dependency=(${dependencies[i]})
  62. project_check "${dependency[0]}" || let missing++
  63. done
  64. return $missing
  65. }
  66. project_dependencies_sources_check() {
  67. local project=$1
  68. shift
  69. local -a dependencies
  70. mapfile -t dependencies < <(project_dependencies "$project" "$@")
  71. local -i count=${#dependencies[@]}
  72. local -i missing=0
  73. for ((i = 0; i < count; i++)); do
  74. local -a dependency=(${dependencies[i]})
  75. project_sources_directory_filled_check "${dependency[0]}" \
  76. || let missing++
  77. done
  78. return $missing
  79. }
  80. project_dependencies_action_arguments() {
  81. local action=$1
  82. local project=$2
  83. shift 2
  84. local -a dependencies
  85. mapfile -t dependencies < <(project_dependencies "$project" "$@")
  86. local -i count=${#dependencies[@]}
  87. for ((i = 0; i < count; i++)); do
  88. local -a dependency=(${dependencies[i]})
  89. if project_function_check "${dependency[0]}" "$action"; then
  90. project_action_arguments "$action" "${dependency[@]}"
  91. fi
  92. done
  93. }
  94. project_function_check() {
  95. local project=$1
  96. local function=$2
  97. project_include "$project"
  98. if ! function_check "$function"
  99. then
  100. return 1
  101. fi
  102. return 0
  103. }
  104. project_action() {
  105. local action="$1"
  106. shift
  107. local project="$1"
  108. shift
  109. local arguments="$*"
  110. (
  111. set +e
  112. project_action_check "$action" "$project" "$@"
  113. printf 1>&2 '%s\n' "Project $project $action (with ${arguments:-no argument})"
  114. if "$action" "$@"; then
  115. printf 1>&2 '\n%s\n' "Project $project $action (with ${arguments:-no argument}) completed"
  116. else
  117. printf 1>&2 '\n%s\n' "Project $project $action (with ${arguments:-no argument}) failed"
  118. return 1
  119. fi
  120. )
  121. }
  122. project_action_check() {
  123. local action="$1"
  124. shift
  125. local project="$1"
  126. shift
  127. (
  128. set +e
  129. if ! function_check "${action}_check"; then
  130. return 1
  131. fi
  132. for project_force in $PROJECTS_FORCE; do
  133. if [[ "$project_force" == "$project" ]]; then
  134. return 1
  135. fi
  136. done
  137. (
  138. set -e
  139. "${action}_check" "$@"
  140. )
  141. )
  142. }
  143. project_action_helper() {
  144. local helper="$1"
  145. shift
  146. local project="$1"
  147. shift
  148. if ! function_check "$helper"; then
  149. return 0
  150. fi
  151. "$helper" "$@"
  152. }
  153. project_action_arguments() {
  154. local action="$1"
  155. shift
  156. local project="$1"
  157. shift
  158. project_include "$project"
  159. project_action_arguments_verify_recursive "$action" "$project" "$@"
  160. project_action_arguments_recursive "$action" "$project" "$@"
  161. }
  162. project_action_arguments_verify_recursive() {
  163. local action="$1"
  164. shift
  165. local project="$1"
  166. shift
  167. local action_helper_arguments
  168. # Store final argument.
  169. local argument="${*:$#}"
  170. local test
  171. if [[ "$#" -gt 1 ]]; then
  172. # Set previous arguments.
  173. set "${@:1:$#-1}"
  174. elif [[ "$#" -eq 1 ]]; then
  175. shift
  176. else
  177. return 0
  178. fi
  179. action_helper_arguments="$(project_action_helper 'arguments' "$project" "$@")"
  180. if [[ -n "$action_helper_arguments" ]]; then
  181. test="$(printf '%s\n' "$action_helper_arguments" | grep -e "^$argument\$" || true)"
  182. if [[ -z "$test" ]]; then
  183. printf 1>&2 '%s\n' "Invalid argument $argument for project $project action $action"
  184. return 1
  185. fi
  186. fi
  187. project_action_arguments_verify_recursive "$action" "$project" "$@"
  188. }
  189. project_action_arguments_recursive() {
  190. local action="$1"
  191. shift
  192. local project="$1"
  193. shift
  194. local action_helper_arguments
  195. local argument
  196. action_helper_arguments="$(project_action_helper 'arguments' "$project" "$@" || true)"
  197. if [[ -z "$action_helper_arguments" ]]; then
  198. project_action "$action" "$project" "$@"
  199. else
  200. # This is to allow space characters in arguments.
  201. local ifs_save="$IFS"
  202. local IFS=$'\n'
  203. for argument in $(printf '%s\n' "$action_helper_arguments")
  204. do
  205. IFS="$ifs_save"
  206. # Only a single argument at a time is returned by the helper.
  207. project_action_arguments_recursive "$action" "$project" "$@" "$argument"
  208. done
  209. fi
  210. }
  211. project_action_projects() {
  212. local action="$1"
  213. shift
  214. local project="$1"
  215. shift
  216. local project_path="$(project_path "$project")"
  217. local project_projects_path="$project_path/$CONFIGS/$PROJECTS"
  218. local project_projects_action_path="$project_path/$CONFIGS/$PROJECTS-$action"
  219. local arguments
  220. local path
  221. if [[ -f "$project_projects_action_path" ]]; then
  222. path="$project_projects_action_path"
  223. else
  224. path="$project_projects_path"
  225. fi
  226. # Multiple arguments can be read from the file.
  227. while read -r arguments; do
  228. eval "project_action_arguments $action $arguments"
  229. done < "$path"
  230. }
  231. project_path() {
  232. local project=$1
  233. local project_path="$root/$PROJECTS/$project"
  234. printf '%s\n' "$project_path"
  235. }
  236. project_sources_path() {
  237. local project=$1
  238. shift
  239. local repository=$1
  240. shift
  241. local sources_path
  242. local argument
  243. local path
  244. # Check downloaded and extracted sources first, using "$project."
  245. path="$root/$SOURCES/$project"
  246. for argument in "" "$@"
  247. do
  248. if [[ -n "$argument" ]]
  249. then
  250. path="$path-$argument"
  251. fi
  252. if ! directory_filled_check "$path"
  253. then
  254. continue
  255. fi
  256. sources_path=$path
  257. done
  258. if [[ -n "$sources_path" ]]
  259. then
  260. printf '%s\n' "$sources_path"
  261. return
  262. fi
  263. # Check downloaded sources then, using "$repository."
  264. path="$root/$SOURCES/$repository"
  265. if directory_filled_check "$path"
  266. then
  267. printf '%s\n' "$path"
  268. return
  269. fi
  270. # Check project sources finally, using "$project."
  271. path="$root/$PROJECTS/$project/$SOURCES"
  272. for argument in "" "$@"
  273. do
  274. if [[ -n "$argument" ]]
  275. then
  276. path="$path/$argument"
  277. fi
  278. if ! directory_filled_check "$path"
  279. then
  280. continue
  281. fi
  282. sources_path=$path
  283. done
  284. if [[ -n "$sources_path" ]]
  285. then
  286. printf '%s\n' "$sources_path"
  287. return
  288. fi
  289. }
  290. project_sources_directory_filled_check() {
  291. local project=$1
  292. shift
  293. local sources_path=$(project_sources_path "$project" "$@")
  294. test ! -z "$sources_path"
  295. }
  296. project_sources_directory_filled_error() {
  297. local project=$1
  298. shift
  299. local arguments="$*"
  300. local sources_path=$(project_sources_path "$project" "$@")
  301. if [[ -n "$sources_path" ]]
  302. then
  303. printf 1>&2 '%s\n' "Sources directory for project $project (with ${arguments:-no argument}) already exists"
  304. return 1
  305. else
  306. return 0
  307. fi
  308. }
  309. project_sources_directory_missing_empty_error() {
  310. local project=$1
  311. shift
  312. local arguments="$*"
  313. local sources_path=$(project_sources_path "$project" "$@")
  314. if [[ -z "$sources_path" ]]
  315. then
  316. printf 1>&2 '%s\n' "Sources directory for project $project (with ${arguments:-no argument}) missing or empty"
  317. return 1
  318. else
  319. return 0
  320. fi
  321. }
  322. project_sources_archive() {
  323. local project=$1
  324. shift
  325. local sources_archive
  326. local argument
  327. local path="$root/$SOURCES/$project"
  328. for argument in "" "$@"
  329. do
  330. if [[ -n "$argument" ]]
  331. then
  332. path="$path-$argument"
  333. fi
  334. local archive="$path.$ARCHIVE"
  335. if ! [[ -f "$archive" ]]
  336. then
  337. continue
  338. fi
  339. sources_archive=$archive
  340. done
  341. if [[ -n "$sources_archive" ]]
  342. then
  343. printf '%s\n' "$sources_archive"
  344. fi
  345. }
  346. project_sources_archive_extract() {
  347. local project=$1
  348. shift
  349. local arguments="$*"
  350. local archive=$(project_sources_archive "$project" "$@")
  351. local destination=$(dirname "$archive")
  352. printf '%s\n' "Extracting source archive for $project (with ${arguments:-no argument})"
  353. file_verification_check "$archive"
  354. archive_extract "$archive" "$destination"
  355. }
  356. project_sources_archive_update() {
  357. local project=$1
  358. shift
  359. local arguments="$*"
  360. local repository=$project
  361. local sources_path=$(project_sources_path "$project" "$repository" "$@")
  362. local archive=$(project_sources_archive "$project" "$@")
  363. local destination=$(dirname "$archive")
  364. if [[ -d "$sources_path" ]]
  365. then
  366. rm -rf "$sources_path"
  367. fi
  368. printf '%s\n' "Extracting source archive for $project (with ${arguments:-no argument})"
  369. file_verification_check "$archive"
  370. archive_extract "$archive" "$destination"
  371. }
  372. project_sources_archive_missing_error() {
  373. local project=$1
  374. shift
  375. local arguments="$*"
  376. local archive=$(project_sources_archive "$project" "$@")
  377. if [[ -z "$archive" ]] || ! [[ -f "$archive" ]]
  378. then
  379. printf 1>&2 '%s\n' "Missing sources archive for $project (with ${arguments:-no argument})"
  380. return 1
  381. else
  382. return 0
  383. fi
  384. }
  385. project_sources_archive_missing_check() {
  386. local project=$1
  387. shift
  388. local archive=$(project_sources_archive "$project" "$@")
  389. if [[ -z "$archive" ]] || ! [[ -f "$archive" ]]
  390. then
  391. return 0
  392. else
  393. return 1
  394. fi
  395. }
  396. project_sources_prepare() {
  397. local project="$1"
  398. local sources_path="$2"
  399. # Not implemented yet / May end up not being needed
  400. #project_sources_prepare_blobs
  401. project_sources_prepare_patch "$project" "$sources_path" "$@"
  402. }
  403. project_sources_prepare_patch() {
  404. local project="$1"
  405. local sources_path="$2"
  406. local project_path="$(project_path "$project")"
  407. local patches_path="$project_path/$PATCHES"
  408. for patch in "$patches_path"/[!.]*.@(patch|diff); do
  409. diff_patch_file "$sources_path" "$patch"
  410. done
  411. }
  412. project_blobs_path() {
  413. local project=$1
  414. shift
  415. local project_path=$(project_path "$project")
  416. local configs_path="$project_path/$CONFIGS"
  417. local argument
  418. local path
  419. for argument in "" "$@"
  420. do
  421. if [[ -n "$argument" ]]
  422. then
  423. if [[ -z "$path" ]]
  424. then
  425. path="$argument"
  426. else
  427. path="$path/$argument"
  428. fi
  429. fi
  430. local blobs_path="$configs_path/$path/$BLOBS"
  431. if [[ -f "$blobs_path" ]]
  432. then
  433. printf '%s\n' "$blobs_path"
  434. return
  435. fi
  436. done
  437. printf '%s\n' "$blobs_path"
  438. }
  439. project_blobs_ignore_path() {
  440. local project=$1
  441. shift
  442. local project_path=$(project_path "$project")
  443. local configs_path="$project_path/$CONFIGS"
  444. local argument
  445. local path
  446. for argument in "" "$@"
  447. do
  448. if [[ -n "$argument" ]]
  449. then
  450. if [[ -z "$path" ]]
  451. then
  452. path="$argument"
  453. else
  454. path="$path/$argument"
  455. fi
  456. fi
  457. blobs_ignore_path="$configs_path/$path/$BLOBS_IGNORE"
  458. if [[ -f "$blobs_ignore_path" ]]
  459. then
  460. printf '%s\n' "$blobs_ignore_path"
  461. return
  462. fi
  463. done
  464. }
  465. project_arguments_targets() {
  466. local project=$1
  467. shift
  468. local project_path=$(project_path "$project")
  469. local targets_path="$project_path/$CONFIGS"
  470. local argument
  471. for argument in "$@"
  472. do
  473. targets_path="$targets_path/$argument"
  474. done
  475. targets_path="$targets_path/$TARGETS"
  476. if [[ -f "$targets_path" ]]
  477. then
  478. cat "$targets_path"
  479. fi
  480. }
  481. project_usage_actions() {
  482. local project="$1"
  483. shift
  484. printf '\n%s\n' 'Generic actions:'
  485. (
  486. for action in "${PROJECT_ACTIONS_GENERIC[@]}"; do
  487. if function_check "$action"; then
  488. printf '%s\n' " $action"
  489. fi
  490. done
  491. )
  492. if [[ "$#" -gt 0 ]]; then
  493. printf '\n%s\n' 'Specific actions:'
  494. (
  495. for action in "$@"; do
  496. printf '%s\n' " $action"
  497. done
  498. )
  499. fi
  500. }
  501. project_usage_arguments() {
  502. local project="$1"
  503. shift
  504. printf '\n%s\n' 'Arguments:'
  505. project_usage_arguments_recursive "$project" ' ' "$@"
  506. }
  507. project_usage_arguments_recursive() {
  508. local project="$1"
  509. shift
  510. local spacing="$1"
  511. shift
  512. local action_helper_arguments
  513. local argument
  514. action_helper_arguments="$(project_action_helper 'arguments' "$project" "$@")"
  515. if [[ -n "$action_helper_arguments" ]]; then
  516. for argument in $action_helper_arguments; do
  517. printf '%s\n' "$spacing$argument"
  518. project_usage_arguments_recursive "$project" " $spacing" "$@" "$argument"
  519. done
  520. fi
  521. }
  522. project_download_git() {
  523. local project=$1
  524. shift
  525. local repository=$1
  526. shift
  527. local urls=$1
  528. shift
  529. requirements "git"
  530. if ! git_project_check "$repository"
  531. then
  532. project_sources_directory_filled_error "$project" "$repository" "$@"
  533. git_project_clone "$repository" "$urls"
  534. fi
  535. git_project_prepare "$project" "$repository" "$@"
  536. }
  537. project_download_check_git() {
  538. local project=$1
  539. shift
  540. local repository=$1
  541. shift
  542. requirements "git"
  543. git_project_check "$repository"
  544. git_project_prepare_check "$project" "$repository" "$@"
  545. }
  546. project_download_archive() {
  547. local project="$1"
  548. shift
  549. local archive_uri="$1"
  550. shift
  551. local archive_dsig_uri="$1"
  552. local archive="${archive_uri##*/}"
  553. local compress_fmt="${archive##*.tar}"
  554. local directory_prefix="$root/$SOURCES"
  555. local archive_path="$root/$SOURCES/$archive"
  556. local sources_path="$root/$SOURCES/$project"
  557. if [[ "${compress_fmt#*.}" != "${ARCHIVE#*.}" ]]; then
  558. ARCHIVE="tar$compress_fmt"
  559. fi
  560. # TODO: Split this code block into separate functions
  561. # Archive verification will be included at that point in time
  562. if ! project_sources_directory_filled_check "$project"; then
  563. download_wrapper "$directory_prefix" "$archive_uri" "$archive_dsig_uri"
  564. archive_extract "$archive_path" "$directory_prefix"
  565. mv "${archive_path%.tar*}" "$sources_path"
  566. fi
  567. # Patch the source, if necessary
  568. project_sources_prepare "$project" "$sources_path"
  569. }
  570. project_download_check_archive() {
  571. local project="$1"
  572. local sources_path="$2"
  573. # TODO: Write the following function
  574. #project_sources_archive_extract_check "$project" "$sources_path"
  575. }
  576. project_extract() {
  577. local project=$1
  578. shift
  579. local repository=$project
  580. if ! project_sources_directory_filled_check "$project" "$repository" "$@"
  581. then
  582. project_sources_archive_missing_error "$project" "$@" || return 1
  583. project_sources_archive_extract "$project" "$@"
  584. fi
  585. }
  586. project_extract_check() {
  587. local project=$1
  588. shift
  589. local repository=$project
  590. project_sources_directory_filled_check "$project" "$repository" "$@"
  591. }
  592. project_update_git() {
  593. local project=$1
  594. shift
  595. local repository=$1
  596. shift
  597. requirements "git"
  598. project_sources_directory_missing_empty_error "$project" "$repository" "$@"
  599. if git_project_check "$repository"
  600. then
  601. git_project_update "$project" "$repository" "$@"
  602. else
  603. if ! project_sources_archive_missing_check "$project" "$@"
  604. then
  605. project_sources_archive_update "$project" "$@"
  606. fi
  607. fi
  608. }
  609. project_update_check_git() {
  610. local project=$1
  611. shift
  612. local repository=$1
  613. shift
  614. requirements "git"
  615. if ! git_project_check "$repository"
  616. then
  617. # Git repository should always be updated (even if upstream didn't progress).
  618. # For instance, this is useful for testing new versions of patches without changing revision.
  619. return 1
  620. else
  621. project_sources_archive_missing_check "$project" "$@"
  622. fi
  623. }
  624. project_build_check() {
  625. local project=$1
  626. shift
  627. local project_path=$(project_path "$project")
  628. local build_path=$(project_build_path "$project" "$@")
  629. local source_file_path
  630. local argument
  631. local rule
  632. local path
  633. for argument in "" "$@"
  634. do
  635. if [[ -n "$argument" ]]
  636. then
  637. if [[ -z "$path" ]]
  638. then
  639. path="$argument"
  640. else
  641. path="$path/$argument"
  642. fi
  643. fi
  644. configs_install_path="$project_path/$CONFIGS/$path/$INSTALL"
  645. if ! [[ -f "$configs_install_path" ]]
  646. then
  647. continue
  648. fi
  649. while read -r rule
  650. do
  651. source=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\1/g")
  652. source_path="$build_path/$source"
  653. # Source may contain a wildcard.
  654. path_wildcard_expand "$source_path" | while read -r source_file_path
  655. do
  656. if ! [[ -f "$source_file_path" ]] && ! [[ -d "$source_file_path" ]]
  657. then
  658. false
  659. fi
  660. done
  661. done < "$configs_install_path"
  662. done
  663. }
  664. project_build_path() {
  665. local project=$1
  666. shift
  667. local build_path="$root/$BUILD/$project"
  668. local argument
  669. for argument in "$@"
  670. do
  671. build_path="$build_path-$argument"
  672. done
  673. printf '%s\n' "$build_path"
  674. }
  675. project_build_directory_missing_empty_error() {
  676. local project=$1
  677. shift
  678. local arguments="$*"
  679. local build_path=$(project_build_path "$project" "$@")
  680. if ! directory_filled_check "$build_path"
  681. then
  682. printf 1>&2 '%s\n' "Build directory for project $project (with ${arguments:-no argument}) missing or empty"
  683. return 1
  684. else
  685. return 0
  686. fi
  687. }
  688. project_install() {
  689. local project=$1
  690. shift
  691. local project_path=$(project_path "$project")
  692. local build_path=$(project_build_path "$project" "$@")
  693. local install_path=$(project_install_path "$project" "$@")
  694. local source_file_path
  695. local argument
  696. local rule
  697. local path
  698. # Install built files first.
  699. for argument in "" "$@"
  700. do
  701. if [[ -n "$argument" ]]
  702. then
  703. if [[ -z "$path" ]]
  704. then
  705. path="$argument"
  706. else
  707. path="$path/$argument"
  708. fi
  709. fi
  710. configs_install_path="$project_path/$CONFIGS/$path/$INSTALL"
  711. if ! [[ -f "$configs_install_path" ]]
  712. then
  713. continue
  714. fi
  715. project_build_directory_missing_empty_error "$project" "$@"
  716. while read -r rule
  717. do
  718. source=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\1/g")
  719. source_path="$build_path/$source"
  720. destination=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\2/g")
  721. destination_path="$install_path/$destination"
  722. destination_directory_path=$(dirname "$destination_path")
  723. mkdir -p "$destination_directory_path"
  724. # Source may contain a wildcard.
  725. path_wildcard_expand "$source_path" | while read -r source_file_path
  726. do
  727. cp -rT "$source_file_path" "$destination_path"
  728. done
  729. done < "$configs_install_path"
  730. done
  731. path=""
  732. # Install install files then.
  733. for argument in "" "$@"
  734. do
  735. if [[ -n "$argument" ]]
  736. then
  737. if [[ -z "$path" ]]
  738. then
  739. path="$argument"
  740. else
  741. path="$path/$argument"
  742. fi
  743. fi
  744. install_install_path="$project_path/$INSTALL/$path/$INSTALL"
  745. if ! [[ -f "$install_install_path" ]]
  746. then
  747. continue
  748. fi
  749. while read -r rule
  750. do
  751. source=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\1/g")
  752. source_path="$project_path/$INSTALL/$path/$source"
  753. destination=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\2/g")
  754. destination_path="$install_path/$destination"
  755. destination_directory_path=$(dirname "$destination_path")
  756. mkdir -p "$destination_directory_path"
  757. # Source may contain a wildcard.
  758. path_wildcard_expand "$source_path" | while read -r source_file_path
  759. do
  760. cp -rT "$source_file_path" "$destination_path"
  761. done
  762. done < "$install_install_path"
  763. done
  764. }
  765. project_install_check() {
  766. local project=$1
  767. shift
  768. local project_path=$(project_path "$project")
  769. local build_path=$(project_build_path "$project" "$@")
  770. local install_path=$(project_install_path "$project" "$@")
  771. local argument
  772. local rule
  773. local path
  774. # Install built files first.
  775. for argument in "" "$@"
  776. do
  777. if [[ -n "$argument" ]]
  778. then
  779. if [[ -z "$path" ]]
  780. then
  781. path="$argument"
  782. else
  783. path="$path/$argument"
  784. fi
  785. fi
  786. configs_install_path="$project_path/$CONFIGS/$path/$INSTALL"
  787. if ! [[ -f "$configs_install_path" ]]
  788. then
  789. continue
  790. fi
  791. project_build_directory_missing_empty_error "$project" "$@"
  792. while read -r rule
  793. do
  794. destination=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\2/g")
  795. destination_path="$install_path/$destination"
  796. if ! [[ -f "$destination_path" ]] && ! [[ -d "$destination_path" ]]
  797. then
  798. false
  799. fi
  800. done < "$configs_install_path"
  801. done
  802. path=""
  803. # Install install files then.
  804. for argument in "" "$@"
  805. do
  806. if [[ -n "$argument" ]]
  807. then
  808. if [[ -z "$path" ]]
  809. then
  810. path="$argument"
  811. else
  812. path="$path/$argument"
  813. fi
  814. fi
  815. install_install_path="$project_path/$INSTALL/$path/$INSTALL"
  816. if ! [[ -f "$install_install_path" ]]
  817. then
  818. continue
  819. fi
  820. while read -r rule
  821. do
  822. destination=$(printf '%s\n' "$rule" | sed "s/$INSTALL_REGEX/\\2/g")
  823. destination_path="$install_path/$destination"
  824. if ! [[ -f "$destination_path" ]] && ! [[ -d "$destination_path" ]]
  825. then
  826. false
  827. fi
  828. done < "$install_install_path"
  829. done
  830. }
  831. project_install_path() {
  832. local project=$1
  833. shift
  834. local install_path="$root/$INSTALL/$project"
  835. local argument
  836. for argument in "$@"
  837. do
  838. install_path="$install_path-$argument"
  839. done
  840. printf '%s\n' "$install_path"
  841. }
  842. project_install_directory_missing_empty_error() {
  843. local project=$1
  844. shift
  845. local arguments="$*"
  846. local install_path=$(project_install_path "$project" "$@")
  847. if ! directory_filled_check "$install_path"
  848. then
  849. printf 1>&2 '%s\n' "Install directory for project $project (with ${arguments:-no argument}) missing or empty"
  850. return 1
  851. else
  852. return 0
  853. fi
  854. }
  855. project_release_path() {
  856. local project=$1
  857. shift
  858. local prefix=$1
  859. local release_path="$root/$RELEASE/$prefix"
  860. # Special care for tools and systems, that depend on the host arch.
  861. if [[ "$prefix" = "$SYSTEMS" ]] || [[ "$prefix" = "$TOOLS" ]]
  862. then
  863. local machine=$(uname -m)
  864. release_path="$release_path/$machine/$project"
  865. else
  866. release_path="$release_path/$project"
  867. fi
  868. printf '%s\n' "$release_path"
  869. }
  870. project_release_archive_path() {
  871. local project=$1
  872. shift
  873. local prefix=$1
  874. shift
  875. local release_path=$(project_release_path "$project" "$prefix")
  876. local argument
  877. local path="$project"
  878. for argument in "$@"
  879. do
  880. path="$path-$argument"
  881. done
  882. local archive_path="$release_path/$path.$ARCHIVE"
  883. printf '%s\n' "$archive_path"
  884. }
  885. project_release_rootfs_path() {
  886. local project=$1
  887. shift
  888. local prefix=$1
  889. shift
  890. local release_path=$(project_release_path "$project" "$prefix")
  891. local argument
  892. local path="$project"
  893. for argument in "$@"
  894. do
  895. path="$path-$argument"
  896. done
  897. local rootfs_path="$release_path/$path.$ARCHIVE"
  898. printf '%s\n' "$rootfs_path"
  899. }
  900. project_release_sources_archive_path() {
  901. local project=$1
  902. shift
  903. local repository="$project"
  904. local sources_path="$(project_sources_path "$project" "$repository" "$@")"
  905. local archive_path="$root/$RELEASE/$SOURCES/$project/${sources_path##*/}.$ARCHIVE"
  906. printf '%s\n' "$archive_path"
  907. }
  908. project_release_sources_archive_create() {
  909. local project=$1
  910. shift
  911. local arguments="$*"
  912. local repository=$project
  913. local archive_path=$(project_release_sources_archive_path "$project" "$@")
  914. local sources_path=$(project_sources_path "$project" "$repository" "$@")
  915. printf '%s\n' "Releasing sources archive for $project (with ${arguments:-no argument})"
  916. archive_create "$archive_path" "$sources_path"
  917. file_verification_create "$archive_path"
  918. }
  919. project_release_sources_archive_exists_check() {
  920. local project=$1
  921. shift
  922. local archive_path=$(project_release_sources_archive_path "$project" "$@")
  923. if [[ -z "$archive_path" ]] || ! [[ -f "$archive_path" ]]
  924. then
  925. return 1
  926. else
  927. return 0
  928. fi
  929. }
  930. project_release_sources_git() {
  931. local project=$1
  932. shift
  933. local repository=$1
  934. shift
  935. requirements "git"
  936. project_sources_directory_missing_empty_error "$project" "$repository" "$@"
  937. if git_project_check "$repository"
  938. then
  939. if ! git_project_release_check "$project" "$repository" "$@"
  940. then
  941. git_project_release "$project" "$repository" "$@"
  942. fi
  943. else
  944. if ! project_release_sources_archive_exists_check "$project" "$@"
  945. then
  946. project_release_sources_archive_create "$project" "$@"
  947. fi
  948. fi
  949. }
  950. project_release_check_sources_git() {
  951. local project=$1
  952. shift
  953. local repository=$1
  954. shift
  955. requirements "git"
  956. if git_project_check "$repository"
  957. then
  958. git_project_release_check "$project" "$repository" "$@"
  959. else
  960. project_release_sources_archive_exists_check "$project" "$@"
  961. fi
  962. }
  963. project_release_install() {
  964. local project=$1
  965. shift
  966. local prefix=$1
  967. shift
  968. local install_path=$(project_install_path "$project" "$@")
  969. local release_path=$(project_release_path "$project" "$prefix")
  970. local directory_path
  971. local path
  972. project_install_directory_missing_empty_error "$project" "$@"
  973. local files=$(find "$install_path" -type f || true)
  974. local file
  975. printf '%s\n' "$files" | while read -r file
  976. do
  977. path="$release_path/$file"
  978. directory_path=$(dirname "$path")
  979. mkdir -p "$directory_path"
  980. cp "$install_path/$file" "$path"
  981. file_verification_create "$path"
  982. done
  983. }
  984. project_release_install_check() {
  985. local project=$1
  986. shift
  987. local prefix=$1
  988. shift
  989. local install_path=$(project_install_path "$project" "$@")
  990. local release_path=$(project_release_path "$project" "$prefix")
  991. local path
  992. project_install_directory_missing_empty_error "$project" "$@"
  993. local files=$(find "$install_path" -type f || true)
  994. local file
  995. printf '%s\n' "$files" | while read -r file
  996. do
  997. path="$release_path/$file"
  998. file_exists_check "$path"
  999. done
  1000. }
  1001. project_release_install_archive() {
  1002. local project=$1
  1003. shift
  1004. local prefix=$1
  1005. shift
  1006. project_install_directory_missing_empty_error "$project" "$@"
  1007. project_release_install_archive_create "$project" "$prefix" "$@"
  1008. }
  1009. project_release_install_archive_check() {
  1010. local project=$1
  1011. shift
  1012. project_release_install_archive_exists_check "$project" "$@"
  1013. }
  1014. project_release_install_archive_create() {
  1015. local project=$1
  1016. shift
  1017. local prefix=$1
  1018. shift
  1019. local arguments="$*"
  1020. local install_path=$(project_install_path "$project" "$@")
  1021. local archive_path=$(project_release_archive_path "$project" "$prefix" "$@")
  1022. printf '%s\n' "Releasing $prefix archive for $project (with ${arguments:-no argument})"
  1023. archive_create "$archive_path" "$install_path"
  1024. file_verification_create "$archive_path"
  1025. }
  1026. project_release_install_archive_exists_check() {
  1027. local project=$1
  1028. shift
  1029. local prefix=$1
  1030. shift
  1031. local archive_path=$(project_release_archive_path "$project" "$prefix" "$@")
  1032. file_exists_check "$archive_path"
  1033. }
  1034. project_release_install_rootfs() {
  1035. local project=$1
  1036. shift
  1037. local prefix=$1
  1038. shift
  1039. project_install_directory_missing_empty_error "$project" "$@"
  1040. if ! project_release_install_rootfs_exists_check "$project" "$prefix" "$@"
  1041. then
  1042. project_release_install_rootfs_create "$project" "$prefix" "$@"
  1043. fi
  1044. }
  1045. project_release_install_rootfs_check() {
  1046. local project=$1
  1047. shift
  1048. project_release_install_rootfs_exists_check "$project" "$@"
  1049. }
  1050. project_release_install_rootfs_create() {
  1051. local project=$1
  1052. shift
  1053. local prefix=$1
  1054. shift
  1055. local arguments="$*"
  1056. local install_path=$(project_install_path "$project" "$@")
  1057. local rootfs_path=$(project_release_rootfs_path "$project" "$prefix" "$@")
  1058. printf '%s\n' "Releasing $prefix rootfs for $project (with ${arguments:-no argument})"
  1059. rootfs_create "$rootfs_path" "$install_path"
  1060. file_verification_create "$rootfs_path"
  1061. }
  1062. project_release_install_rootfs_exists_check() {
  1063. local project=$1
  1064. shift
  1065. local prefix=$1
  1066. shift
  1067. local rootfs_path=$(project_release_rootfs_path "$project" "$prefix" "$@")
  1068. file_exists_check "$rootfs_path"
  1069. }
  1070. project_clean() {
  1071. local project=$1
  1072. shift
  1073. project_clean_build "$project" "$@"
  1074. project_clean_install "$project" "$@"
  1075. project_clean_release "$project" "$@"
  1076. }
  1077. project_clean_build() {
  1078. local project=$1
  1079. shift
  1080. local build_path=$(project_build_path "$project" "$@")
  1081. rm -rf "$build_path"
  1082. }
  1083. project_clean_install() {
  1084. local project=$1
  1085. shift
  1086. local install_path=$(project_install_path "$project" "$@")
  1087. rm -rf "$install_path"
  1088. }
  1089. project_clean_release() {
  1090. local project=$1
  1091. shift
  1092. local prefix
  1093. for prefix in "$SOURCES" "$SYSTEMS" "$IMAGES" "$TOOLS" "$DOCS"
  1094. do
  1095. local release_path=$(project_release_path "$project" "$prefix")
  1096. rm -rf "$release_path"
  1097. done
  1098. }
  1099. project_clean_rootfs() {
  1100. local project=$1
  1101. shift
  1102. project_clean_build "$project" "$@"
  1103. project_clean_rootfs_install "$project" "$@"
  1104. project_clean_release "$project" "$@"
  1105. }
  1106. project_clean_rootfs_install() {
  1107. local project=$1
  1108. shift
  1109. local install_path=$(project_install_path "$project" "$@")
  1110. execute_root rm -rf "$install_path"
  1111. }
  1112. project_file_path() {
  1113. local project=$1
  1114. shift
  1115. local directory=$1
  1116. shift
  1117. local file=$1
  1118. shift
  1119. local project_path=$(project_path "$project")
  1120. local path="$project_path/$directory"
  1121. local argument
  1122. local file_path
  1123. for argument in "" "$@"
  1124. do
  1125. if [[ -n "$argument" ]]
  1126. then
  1127. path="$path/$argument"
  1128. fi
  1129. if ! [[ -f "$path/$file" ]]
  1130. then
  1131. continue
  1132. fi
  1133. file_path="$path/$file"
  1134. break
  1135. done
  1136. if [[ -z "$file_path" ]]
  1137. then
  1138. return 1
  1139. fi
  1140. printf '%s\n' "$file_path"
  1141. }
  1142. project_file_test() {
  1143. local file_path=$(project_file_path "$@")
  1144. test -f "$file_path"
  1145. }
  1146. project_file_contents() {
  1147. local file_path=$(project_file_path "$@")
  1148. if [[ -f "$file_path" ]]
  1149. then
  1150. cat "$file_path"
  1151. fi
  1152. }
  1153. project_file_contents_herit() {
  1154. local project=$1
  1155. shift
  1156. local directory=$1
  1157. shift
  1158. local file=$1
  1159. shift
  1160. local project_path=$(project_path "$project")
  1161. local path="$project_path/$directory"
  1162. local argument
  1163. local file_path
  1164. for argument in "" "$@"
  1165. do
  1166. if [[ -n "$argument" ]]
  1167. then
  1168. path="$path/$argument"
  1169. fi
  1170. file_path="$path/$file"
  1171. if ! [[ -f "$file_path" ]]
  1172. then
  1173. continue
  1174. fi
  1175. cat "$file_path"
  1176. done
  1177. }