cocktail 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. #!/bin/bash
  2. RC_OK=0
  3. RC_ERROR=1
  4. RC_LOCK=2
  5. RC_CONFIG_MISSED=3
  6. RC_CONFIG_PARAM=4
  7. RC_PANDOC_FILES=5
  8. RC_ARGS=6
  9. RC_ARGS_DOSSIER=7
  10. RC_ARGS_PROJET=8
  11. RC_ARGS_ACTION=9
  12. end_with_code() {
  13. local rc=$1
  14. if test -z "$rc";
  15. then
  16. rc=$RC_ERROR
  17. fi
  18. if test "$rc" -eq 0;
  19. then
  20. cleanup_working_folder
  21. fi
  22. verbose "[$FUNCNAME] exiting with RC=[$rc]"
  23. exit $rc
  24. }
  25. die() {
  26. verbose "[$FUNCNAME] 1:[$1] 2:[$2]"
  27. local message
  28. local rc
  29. if test $# -eq 2;
  30. then
  31. message=$1
  32. rc=$2
  33. else
  34. message=$1
  35. rc=$RC_ERROR
  36. fi
  37. echo -e "$$ $message" >&2
  38. end_with_code $rc
  39. }
  40. verbose() {
  41. if test -n "$VERBOSE";
  42. then
  43. if test "$VERBOSE" -ne 0;
  44. then
  45. echo "$$ $@"
  46. fi
  47. fi
  48. }
  49. debug() {
  50. if test "$DEBUG" -ne 0;
  51. then
  52. echo "$@"
  53. fi
  54. }
  55. init_check() {
  56. if test -e $LOCK_FILE;
  57. then
  58. die "[$FUNCNAME] lock=$LOCK_FILE exists. Wait compilation or erase it" $RC_LOCK
  59. fi
  60. # PANDOC_FILTER_BASE should exists
  61. if test ! -d "$PANDOC_FILTER_BASE";
  62. then
  63. die "[$FUNCNAME]: PANDOC_FILTER_BASE=$PANDOC_FILTER_BASE unavailable" $RC_PANDOC_FILES
  64. fi
  65. # PANDOC_INCLUDE_BASE should exists
  66. if test ! -d "$PANDOC_INCLUDE_BASE";
  67. then
  68. die "[$FUNCNAME]: PANDOC_INCLUDE_BASE=$PANDOC_INCLUDE_BASE unavailable" $RC_PANDOC_FILES
  69. fi
  70. # STORE should exists
  71. if test ! -d "$STORE" -o ! -w "$STORE";
  72. then
  73. die "[$FUNCNAME]: STORE=$STORE should be a writable folder"
  74. fi
  75. # WORKING_FOLDER should exists
  76. if test ! -d "$WORKING_FOLDER" -o ! -w "$WORKING_FOLDER";
  77. then
  78. die "[$FUNCNAME]: WORKING_FOLDER=$WORKING_FOLDER should be a writable folder"
  79. fi
  80. # MIRRORPAD shoud exists and executable
  81. if test ! -x "$MIRRORPAD";
  82. then
  83. die "[$FUNCNAME]: MIRRORPAD=$MIRRORPAD should be an axecutable file"
  84. fi
  85. # external tools
  86. for tool in touch pandoc pdflatex
  87. do
  88. local tool_location=$(command -v $tool)
  89. if test "$tool_location";
  90. then
  91. verbose "[$FUNCNAME] $tool=$tool_location"
  92. else
  93. die "[$FUNCNAME] $tool unavailable"
  94. fi
  95. done
  96. }
  97. mirror_pad() {
  98. debug "[$FUNCNAME] ARGS:$@"
  99. if test $# -ne 2;
  100. then
  101. die 'usage: [$FUNCNAME] url filename'
  102. fi
  103. local url=$1
  104. local filename=$2
  105. verbose "[$FUNCNAME] url=$url filename=$filename"
  106. RESPONSE=$($MIRRORPAD $url > "$filename")
  107. RC=$?
  108. local errstr="[$FUNCNAME] RC=[$RC] $RESPONSE"
  109. if test "$RC" -eq 0;
  110. then
  111. verbose "$errstr"
  112. else
  113. die "$errstr"
  114. fi
  115. }
  116. pad2json() {
  117. debug "[$FUNCNAME] ARGS:$@"
  118. if test $# -ne 2;
  119. then
  120. die "usage: [$FUNCNAME] input_file output_file"
  121. fi
  122. local input=$1
  123. local output=$2
  124. verbose "[$FUNCNAME] input=$input output=$output"
  125. RESPONSE=$(pandoc \
  126. -f markdown "$input" \
  127. -o "$output" -t json --self-contained)
  128. RC=$?
  129. local errstr="[$FUNCNAME] RC=[$RC] $RESPONSE"
  130. if test "$RC" -eq 0;
  131. then
  132. verbose "$errstr"
  133. else
  134. die "$errstr"
  135. fi
  136. }
  137. pad2docx() {
  138. debug "[$FUNCNAME] PWD:$PWD ARGS:$@"
  139. if test $# -ne 2;
  140. then
  141. die 'usage: [$FUNCNAME] input_file output_file'
  142. fi
  143. local input=$1
  144. local output=$2
  145. local refdoc="$PANDOC_INCLUDE_BASE/spinosi.docx"
  146. verbose "[$FUNCNAME] input=$input output=$output"
  147. if ! test -e "$refdoc";
  148. then
  149. die "[$FUNCNAME] refdoc=$refdoc unavailable"
  150. fi
  151. RESPONSE=$(pandoc \
  152. -f markdown "$input" \
  153. -o "$output" -t docx --self-contained --smart \
  154. --reference-docx="$refdoc" \
  155. --filter pandoc-citeproc \
  156. --filter $PANDOC_FILTER_BASE/docx.zsh \
  157. --filter $PANDOC_FILTER_BASE/nettoyage.zsh \
  158. --filter $PANDOC_FILTER_BASE/nettoyage-etendu.zsh)
  159. RC=$?
  160. local errstr="[$FUNCNAME] RC=[$RC] $RESPONSE"
  161. if test "$RC" -eq 0;
  162. then
  163. verbose "$errstr"
  164. else
  165. die "$errstr"
  166. fi
  167. }
  168. pad2html() {
  169. debug "[$FUNCNAME] ARGS:$@"
  170. if test $# -ne 2;
  171. then
  172. die 'usage: [$FUNCNAME] input_file output_file'
  173. fi
  174. local input=$1
  175. local output=$2
  176. verbose "[$FUNCNAME] input=$input output=$output"
  177. RESPONSE=$(pandoc \
  178. -f markdown "$input" \
  179. -o "$output" -t html --self-contained --smart \
  180. --filter pandoc-citeproc \
  181. --filter $PANDOC_FILTER_BASE/html.zsh \
  182. --filter $PANDOC_FILTER_BASE/nettoyage.zsh \
  183. --filter $PANDOC_FILTER_BASE/nettoyage-etendu.zsh \
  184. --metadata header-includes="<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">")
  185. RC=$?
  186. local errstr="[$FUNCNAME] RC=[$RC] $RESPONSE"
  187. if test "$RC" -eq 0;
  188. then
  189. verbose "$errstr"
  190. else
  191. die "$errstr"
  192. fi
  193. }
  194. pad2markdown() {
  195. debug "[$FUNCNAME] ARGS:$@"
  196. if test $# -ne 2;
  197. then
  198. die 'usage: [$FUNCNAME] input_file output_file'
  199. fi
  200. local input=$1
  201. local output=$2
  202. verbose "[$FUNCNAME] input=$input output=$output"
  203. RESPONSE=$(pandoc \
  204. -f markdown "$input" \
  205. -o "$output" -t markdown_strict --wrap=none --smart \
  206. --reference-location=block --reference-links \
  207. --filter pandoc-citeproc \
  208. --filter $PANDOC_FILTER_BASE/markdown_strict.zsh \
  209. --filter $PANDOC_FILTER_BASE/nettoyage.zsh \
  210. --filter $PANDOC_FILTER_BASE/nettoyage-etendu.zsh)
  211. RC=$?
  212. local errstr="[$FUNCNAME] RC=[$RC] $RESPONSE"
  213. if test "$RC" -eq 0;
  214. then
  215. verbose "$errstr"
  216. else
  217. die "$errstr"
  218. fi
  219. }
  220. pad2tex() {
  221. debug "[$FUNCNAME] ARGS:$@"
  222. if test $# -ne 2;
  223. then
  224. die 'usage: [$FUNCNAME] input_file output_file'
  225. fi
  226. local input=$1
  227. local output=$2
  228. verbose "[$FUNCNAME] input=$input output=$output"
  229. RESPONSE=$(pandoc \
  230. -f markdown "$input" \
  231. -o "$output" -t latex --self-contained \
  232. --template ../../exegetesDoc/pandocincludes/exegetes.latex \
  233. --filter pandoc-citeproc \
  234. --filter $PANDOC_FILTER_BASE/latex.zsh \
  235. --filter $PANDOC_FILTER_BASE/nettoyage.zsh \
  236. --filter pandoc-latex-environment \
  237. --filter $PANDOC_FILTER_BASE/paranumero.bash)
  238. RC=$?
  239. local errstr="[$FUNCNAME] RC=[$RC] $RESPONSE"
  240. if test "$RC" -eq 0;
  241. then
  242. verbose "$errstr"
  243. else
  244. die "$errstr"
  245. fi
  246. }
  247. pad2texinput() {
  248. debug "[$FUNCNAME] ARGS:$@"
  249. if test $# -ne 2;
  250. then
  251. die 'usage: [$FUNCNAME] input_file output_file'
  252. fi
  253. local input=$1
  254. local output=$2
  255. verbose "[$FUNCNAME] input=$input output=$output"
  256. RESPONSE=$(pandoc \
  257. -f markdown "$input" \
  258. -o "$output" -t latex \
  259. --filter pandoc-citeproc \
  260. --filter $PANDOC_FILTER_BASE/latex.zsh \
  261. --filter $PANDOC_FILTER_BASE/nettoyage.zsh \
  262. --filter pandoc-latex-environment \
  263. --filter $PANDOC_FILTER_BASE/paranumero.bash)
  264. RC=$?
  265. local errstr="[$FUNCNAME] RC=[$RC] $RESPONSE"
  266. if test "$RC" -eq 0;
  267. then
  268. verbose "$errstr"
  269. else
  270. die "$errstr"
  271. fi
  272. }
  273. tex2pdf() {
  274. debug "[$FUNCNAME] ARGS:$@"
  275. if test $# -ne 2;
  276. then
  277. die 'usage: [$FUNCNAME] input_file output_file'
  278. fi
  279. local input=$1
  280. local output=$2
  281. verbose "[$FUNCNAME] input=$input output=$output"
  282. # pdflatex sort avec un code 1 mais genere le PDF on peut pas die sur RC>0 ici
  283. pdflatex -interaction=nonstopmode -output-directory="$WORKING_FOLDER" "$input" > "$WORKING_FOLDER/pdflatex_passe1.log" 2>&1
  284. verbose "[$FUNCNAME] Passe 1 RC=[$?]"
  285. pdflatex -interaction=nonstopmode -output-directory="$WORKING_FOLDER" "$input" > "$WORKING_FOLDER/pdflatex_passe2.log" 2>&1
  286. verbose "[$FUNCNAME] Passe 2 RC=[$?]"
  287. if test ! -e "$output";
  288. then
  289. die "[$FUNCNAME] Génération du PDF '$putput' en erreur"
  290. fi
  291. }
  292. lock_project() {
  293. verbose "[$FUNCNAME] LOCKFILE=$LOCK_FILE PID=$$ locked"
  294. if test ! -e "$LOCK_FILE";
  295. then
  296. echo "$$" > "$LOCK_FILE"
  297. else
  298. die "lockfile $LOCK_FILE already exists" $RC_LOCK
  299. fi
  300. }
  301. unlock_project() {
  302. if test -e "$LOCK_FILE";
  303. then
  304. local locker_pid=$(cat "$LOCK_FILE")
  305. verbose "[$FUNCNAME] lockfile=$LOCK_FILE lockerpid=$locker_pid pid=$$"
  306. if test "$locker_pid" -eq "$$";
  307. then
  308. rm -f "$LOCK_FILE"
  309. if test ! -e "$LOCK_FILE";
  310. then
  311. verbose "[$FUNCNAME] $PROJET unlocked, $LOCK_FILE removed."
  312. else
  313. die"[$FUNCNAME] we can not unlock $PROJET, $LOCK_FILE still on disk." $RC_LOCK
  314. fi
  315. else
  316. die "[$FUNCNAME] we can not delete lockfile owned by another process" $RC_LOCK
  317. fi
  318. fi
  319. }
  320. cleanup_working_folder() {
  321. verbose "[$FUNCNAME] WORKING_FOLDER=$WORKING_FOLDER"
  322. if test -n "$WORKING_FOLDER" -a -d "$WORKING_FOLDER";
  323. then
  324. if test "$VERBOSE" -eq 1;
  325. then
  326. rm --recursive --verbose "$WORKING_FOLDER"
  327. else
  328. rm --recursive "$WORKING_FOLDER"
  329. fi
  330. if test ! -d "$WORKING_FOLDER";
  331. then
  332. verbose "[$FUNCNAME] $WORKING_FOLDER removed"
  333. fi
  334. fi
  335. }
  336. usage() {
  337. echo "
  338. cocktail -b url_base -d dossier [ -h ] -p projet [ -g url_garde ] [ -v ]
  339. -b : url du pad principal
  340. -d : nom du dossier
  341. -g : url du pad de page de garde (optionnel)
  342. -h : cette page d'aide
  343. -p : nom du projet
  344. -v : force le mode verbeux
  345. return codes:
  346. 0 : OK
  347. 1 : GENERIC ERROR
  348. 2 : LOCK ERROR
  349. 3 : CONFIG FILE IS MISSING
  350. 4 : PANDOC FILTER IS MISSING OR NOT EXECUTABLE
  351. 5 : ARGUMENTS ERRORS"
  352. }
  353. publish() {
  354. local src_folder="$1"
  355. local dst_folder="$2"
  356. verbose "[$FUNCNAME] SOURCE=$src_folder DESTINATION=$dst_folder"
  357. if test ! -d "$src_folder";
  358. then
  359. die "[$FUNCNAME] the folder '$src_folder' does not exists"
  360. fi
  361. if test ! -d "$dst_folder";
  362. then
  363. die "[$FUNCNAME] the folder '$dst_folder' does not exists"
  364. fi
  365. for ext in pdf docx html md texinput tex txt
  366. do
  367. local from="$src_folder/$PROJET.$ext"
  368. local to="$dst_folder/$PROJET.$ext"
  369. verbose "$from -> $to"
  370. cp -f "$from" "$to"
  371. done
  372. }
  373. ### MAIN ###
  374. base=$( cd $( dirname "${BASH_SOURCE[0]}" ) && pwd )
  375. if test -r "$base/cocktail.conf";
  376. then
  377. source "$base/cocktail.conf"
  378. error_in_config=0
  379. # Should be in config file
  380. if test -z "$PANDOC_FILTER_BASE";
  381. then
  382. echo "$$ PANDOC_FILTER_BASE not found in config file"
  383. error_in_config=1
  384. fi
  385. if test -z "$PANDOC_INCLUDE_BASE";
  386. then
  387. echo "$$ PANDOC_INCLUDE_BASE not found in config file"
  388. error_in_config=1
  389. fi
  390. if test -z "$WORKING_FOLDER";
  391. then
  392. echo "$$ WORKING_FOLDER not found in config file"
  393. fi
  394. if test -z "$STORE";
  395. then
  396. echo "$$ STORE not found in config file"
  397. fi
  398. if test -z "$MIRRORPAD";
  399. then
  400. echo "$$ MIRRORPAD not found in config file"
  401. fi
  402. if test "$error_in_config" -eq 1;
  403. then
  404. die "Errors in config file, maybee empty ?" $RC_CONFIG_PARAM
  405. fi
  406. else
  407. die "cocktail.conf is missing, see config.conf.smp for example" $RC_CONFIG_MISSED
  408. fi
  409. OPTERR=1
  410. while getopts "a:b:d:g:p:hv" option;
  411. do
  412. case $option in
  413. a)
  414. # ATTENTION ^^ = passage en majuscules
  415. ACTION="${OPTARG^^}"
  416. verbose "getopts: -$option) ACTION=$ACTION"
  417. ;;
  418. b)
  419. URL_BASE=$OPTARG
  420. verbose "getopts: -$option) URL_BASE=$URL_BASE"
  421. ;;
  422. d)
  423. DOSSIER=$OPTARG
  424. verbose "getopts: -$option) DOSSIER=$DOSSIER"
  425. ;;
  426. g)
  427. URL_GARDE=$OPTARG
  428. verbose "getopts: -$option) URL_GARDE=$URL_GARDE"
  429. ;;
  430. h)
  431. usage
  432. exit
  433. ;;
  434. p)
  435. PROJET=$OPTARG
  436. verbose "getopts: -$option) PROJET=$PROJET"
  437. ;;
  438. v)
  439. # Override verbose
  440. VERBOSE=1
  441. verbose "getopts: -$option) VERBOSE=$VERBOSE"
  442. ;;
  443. esac
  444. done
  445. shift $(($OPTIND - 1))
  446. verbose "ARGS=$@"
  447. ###############################################################################
  448. # GESTION DES ARGUMENTS DE LA LIGNE DE COMMANDE
  449. ###############################################################################
  450. # ACTION : SHAKE est la valeur par défaut
  451. if test -z "$ACTION";
  452. then
  453. ACTION="SHAKE"
  454. fi
  455. # ACTION : uniquement SHAKE ou UNLOCK
  456. if test "$ACTION" != "SHAKE" -a "$ACTION" != "UNLOCK";
  457. then
  458. die "getopts: -a ne peut être que SHAKE ou UNLOCK" $RC_ARGS_ACTION
  459. fi
  460. verbose "ACTION=$ACTION"
  461. if test -z "$DOSSIER";
  462. then
  463. die "getopts: -d DOSSIER is mandatory" $RC_ARGS
  464. fi
  465. verbose "DOSSIER=$DOSSIER"
  466. if [[ ! $DOSSIER =~ ^[a-zA-Z0-9_-]+$ ]];
  467. then
  468. die "DOSSIER ne peut contenir que des chiffres, des lettres, - ou _" $RC_ARGS_DOSSIER
  469. fi
  470. verbose "PROJET:$PROJET"
  471. if [[ ! $PROJET =~ ^[a-zA-Z0-9_-]+$ ]];
  472. then
  473. die "PROJET ne peut contenir que des chiffres, des lettres, - ou _" $RC_ARGS_PROJET
  474. fi
  475. WORKING_FOLDER="$WORKING_FOLDER/$PROJET"
  476. verbose "WORKING_FOLDER=$WORKING_FOLDER"
  477. mkdir -p "$WORKING_FOLDER"
  478. cd "$WORKING_FOLDER" || die "we can't change to \"$WORKING_FOLDER\" folder"
  479. STORE="$STORE/$DOSSIER"
  480. verbose "STORE=$STORE"
  481. mkdir -p "$STORE"
  482. LOCK_FILE="$STORE/$PROJET.lock"
  483. verbose "LOCK_FILE=$LOCK_FILE"
  484. if test -z "$URL_BASE";
  485. then
  486. die "getopts: -b URL_BASE is mandatory" $RC_ARGS
  487. fi
  488. init_check
  489. lock_project
  490. mirror_pad "$URL_BASE" "$WORKING_FOLDER/$PROJET.txt"
  491. if test "$URL_GARDE";
  492. then
  493. mirror_pad "$URL_GARDE" "$WORKING_FOLDER/garde.tex"
  494. fi
  495. # hack specifique Abro Tele2
  496. touch "$WORKING_FOLDER/annexe-tableau.tex"
  497. pad2json "$WORKING_FOLDER/$PROJET.txt" "$WORKING_FOLDER/$PROJET.json"
  498. pad2docx "$WORKING_FOLDER/$PROJET.txt" "$WORKING_FOLDER/$PROJET.docx"
  499. pad2html "$WORKING_FOLDER/$PROJET.txt" "$WORKING_FOLDER/$PROJET.html"
  500. pad2markdown "$WORKING_FOLDER/$PROJET.txt" "$WORKING_FOLDER/$PROJET.md"
  501. pad2tex "$WORKING_FOLDER/$PROJET.txt" "$WORKING_FOLDER/$PROJET.tex"
  502. pad2texinput "$WORKING_FOLDER/$PROJET.txt" "$WORKING_FOLDER/$PROJET.texinput"
  503. tex2pdf "$WORKING_FOLDER/$PROJET.tex" "$WORKING_FOLDER/$PROJET.pdf"
  504. publish "$WORKING_FOLDER" "$STORE"
  505. unlock_project
  506. end_with_code $RC_OK