project 29 KB

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