summary refs log tree commit diff stats
path: root/compiler/gorgeimpl.nim
blob: 4e1ce6d507a9647c1078adfaf639f85c451bb342 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#
#
#           The Nim Compiler
#        (c) Copyright 2017 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

## Module that implements ``gorge`` for the compiler as well as
## the scriptable import mechanism.

import msgs, securehash, os, osproc, streams, strutils, options

proc readOutput(p: Process): (string, int) =
  result[0] = ""
  var output = p.outputStream
  while not output.atEnd:
    result[0].add(output.readLine)
    result[0].add("\n")
  if result[0].len > 0:
    result[0].setLen(result[0].len - "\n".len)
  result[1] = p.waitForExit

proc opGorge*(cmd, input, cache: string, info: TLineInfo): (string, int) =
  let workingDir = parentDir(info.toFullPath)
  if cache.len > 0:# and optForceFullMake notin gGlobalOptions:
    let h = secureHash(cmd & "\t" & input & "\t" & cache)
    let filename = options.toGeneratedFile("gorge_" & $h, "txt")
    var f: File
    if open(f, filename):
      result = (f.readAll, 0)
      f.close
      return
    var readSuccessful = false
    try:
      var p = startProcess(cmd, workingDir,
                           options={poEvalCommand, poStderrToStdout})
      if input.len != 0:
        p.inputStream.write(input)
        p.inputStream.close()
      result = p.readOutput
      readSuccessful = true
      # only cache successful runs:
      if result[1] == 0:
        writeFile(filename, result[0])
    except IOError, OSError:
      if not readSuccessful: result = ("", -1)
  else:
    try:
      var p = startProcess(cmd, workingDir,
                           options={poEvalCommand, poStderrToStdout})
      if input.len != 0:
        p.inputStream.write(input)
        p.inputStream.close()
      result = p.readOutput
    except IOError, OSError:
      result = ("", -1)

proc scriptableImport*(pkg, subdir: string; info: TLineInfo): string =
  var cmd = getConfigVar("resolver.exe")
  if cmd.len == 0: cmd = "nimresolve"
  else: cmd = quoteShell(cmd)
  cmd.add " --source:"
  cmd.add quoteShell(info.toFullPath())
  cmd.add " --stdlib:"
  cmd.add quoteShell(options.libpath)
  cmd.add "  --project:"
  cmd.add quoteShell(gProjectFull)
  if subdir.len != 0:
    cmd.add " --subdir:"
    cmd.add quoteShell(subdir)
  if options.gNoNimblePath:
    cmd.add " --nonimblepath"
  cmd.add ' '
  cmd.add quoteShell(pkg)
  let (res, exitCode) = opGorge(cmd, "", cmd, info)
  if exitCode == 0:
    result = res.strip()
  elif res.len > 0:
    localError(info, res)
  else:
    localError(info, "cannot resolve: " & (pkg / subdir))