1#
2#
3#           The Nim Compiler
4#        (c) Copyright 2017 Andreas Rumpf
5#
6#    See the file "copying.txt", included in this
7#    distribution, for details about the copyright.
8#
9
10## Module that implements ``gorge`` for the compiler.
11
12import msgs, std / sha1, os, osproc, streams, options,
13  lineinfos, pathutils
14
15proc readOutput(p: Process): (string, int) =
16  result[0] = ""
17  var output = p.outputStream
18  while not output.atEnd:
19    result[0].add(output.readLine)
20    result[0].add("\n")
21  if result[0].len > 0:
22    result[0].setLen(result[0].len - "\n".len)
23  result[1] = p.waitForExit
24
25proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (string, int) =
26  let workingDir = parentDir(toFullPath(conf, info))
27  if cache.len > 0:
28    let h = secureHash(cmd & "\t" & input & "\t" & cache)
29    let filename = toGeneratedFile(conf, AbsoluteFile("gorge_" & $h), "txt").string
30    var f: File
31    if optForceFullMake notin conf.globalOptions and open(f, filename):
32      result = (f.readAll, 0)
33      f.close
34      return
35    var readSuccessful = false
36    try:
37      var p = startProcess(cmd, workingDir,
38                           options={poEvalCommand, poStdErrToStdOut})
39      if input.len != 0:
40        p.inputStream.write(input)
41        p.inputStream.close()
42      result = p.readOutput
43      p.close()
44      readSuccessful = true
45      # only cache successful runs:
46      if result[1] == 0:
47        writeFile(filename, result[0])
48    except IOError, OSError:
49      if not readSuccessful: result = ("", -1)
50  else:
51    try:
52      var p = startProcess(cmd, workingDir,
53                           options={poEvalCommand, poStdErrToStdOut})
54      if input.len != 0:
55        p.inputStream.write(input)
56        p.inputStream.close()
57      result = p.readOutput
58      p.close()
59    except IOError, OSError:
60      result = ("", -1)
61