cocktail 12 KB

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