structure Recovery:
sig
val createMissingDirectories:
{execlog: string, auxfile: string, outdir: string}
-> bool
val runEpstopdf:
{ options: AppOptions.options
, execlog: string
, originalWorkingDirectory: string
}
-> bool
val tryRecovery:
{ options: AppOptions.options
, execlog: string
, auxfile: string
, originalWorkingDirectory: string
}
-> bool
end =
struct
fun createMissingDirectories {execlog, auxfile, outdir} =
if String.isSubstring "I can't write on file" execlog then
(* There is a possibility that there are some subfiles under subdirectories.
* Directories for sub-auxfiles are not created automatically, so we need to provide them. *)
let
val (madeNewDirectory, _) =
AuxFile.createMissingDirectories
{auxfile = auxfile, outdir = outdir, seen = StringSet.empty}
in
if madeNewDirectory andalso Message.getVerbosity () >= 1 then
Message.info "Created missing directories."
else
();
madeNewDirectory
end
else
false
fun runEpstopdf
{ options: AppOptions.options
, execlog: string
, originalWorkingDirectory: string
} =
if #shell_escape options <> SOME ShellEscape.FORBIDDEN then (* (possibly restricted) \write18 enabled *)
let
val lines =
Substring.tokens (fn c => c = #"\n") (Substring.full execlog)
fun doLine (line, run) =
case List.map Substring.string (Substring.tokens Char.isSpace line) of
["(epstopdf)", "Command:", command, outfile', infile'] =>
if
command = "<epstopdf"
orelse
command = "<repstopdf"
andalso String.isPrefix "--outfile=" outfile'
andalso String.isSuffix ">" infile'
then
let
val outfile = String.extract (outfile', 10, NONE)
val infile = String.substring
(infile', 0, String.size infile' - 1)
val infileAbs =
PathUtil.abspath
{path = infile, cwd = SOME originalWorkingDirectory}
in
if FSUtil.isFile infileAbs then (* input file exists *)
let
val outfileAbs = PathUtil.abspath
{path = outfile, cwd = SOME (#output_directory options)}
val () =
if Message.getVerbosity () >= 1 then
Message.info ("Running epstopdf on " ^ infile ^ ".")
else
()
val outdir = PathUtil.dirname outfileAbs
val () =
if not (FSUtil.isDirectory outdir) then
FSUtil.mkDirRec outdir
else
()
val command =
"epstopdf --outfile=" ^ ShellUtil.escape outfileAbs
^ " " ^ ShellUtil.escape infileAbs
val () = Message.exec command
val success =
OS.Process.isSuccess (OS.Process.system command)
in
run orelse success
end
else
run
end
else
run
| _ => run
in
List.foldl doLine false lines
end
else
false
(* The next time we will able to set \PassOptionsToPackage{outputdir=}{minted} *)
fun checkMinted {execlog} =
String.isSubstring
"Package minted Error: Missing Pygments output; \\inputminted was" execlog
fun tryRecovery {options, execlog, auxfile, originalWorkingDirectory} =
let
val recovered =
createMissingDirectories
{ execlog = execlog
, auxfile = auxfile
, outdir = #output_directory options
}
val recovered =
runEpstopdf
{ options = options
, execlog = execlog
, originalWorkingDirectory = originalWorkingDirectory
} orelse recovered
val recovered = recovered orelse checkMinted {execlog = execlog}
in
recovered
end
end;