cocktail 10 KB

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