/src/luarocks/command_line.lua

http://github.com/keplerproject/luarocks · Lua · 194 lines · 165 code · 18 blank · 11 comment · 36 complexity · 1057ca44742759775427cf5568f5c3d4 MD5 · raw file

  1. --- Functions for command-line scripts.
  2. local command_line = {}
  3. local unpack = unpack or table.unpack
  4. local util = require("luarocks.util")
  5. local cfg = require("luarocks.cfg")
  6. local path = require("luarocks.path")
  7. local dir = require("luarocks.dir")
  8. local deps = require("luarocks.deps")
  9. local fs = require("luarocks.fs")
  10. local program = util.this_program("luarocks")
  11. --- Display an error message and exit.
  12. -- @param message string: The error message.
  13. -- @param exitcode number: the exitcode to use
  14. local function die(message, exitcode)
  15. assert(type(message) == "string")
  16. local ok, err = pcall(util.run_scheduled_functions)
  17. if not ok then
  18. util.printerr("\nLuaRocks "..cfg.program_version.." internal bug (please report at https://github.com/keplerproject/luarocks/issues):\n"..err)
  19. end
  20. util.printerr("\nError: "..message)
  21. os.exit(exitcode or cfg.errorcodes.UNSPECIFIED)
  22. end
  23. local function replace_tree(flags, tree)
  24. tree = dir.normalize(tree)
  25. flags["tree"] = tree
  26. path.use_tree(tree)
  27. end
  28. --- Main command-line processor.
  29. -- Parses input arguments and calls the appropriate driver function
  30. -- to execute the action requested on the command-line, forwarding
  31. -- to it any additional arguments passed by the user.
  32. -- Uses the global table "commands", which contains
  33. -- the loaded modules representing commands.
  34. -- @param ... string: Arguments given on the command-line.
  35. function command_line.run_command(...)
  36. local args = {...}
  37. local cmdline_vars = {}
  38. for i = #args, 1, -1 do
  39. local arg = args[i]
  40. if arg:match("^[^-][^=]*=") then
  41. local var, val = arg:match("^([A-Z_][A-Z0-9_]*)=(.*)")
  42. if val then
  43. cmdline_vars[var] = val
  44. table.remove(args, i)
  45. else
  46. die("Invalid assignment: "..arg)
  47. end
  48. end
  49. end
  50. local nonflags = { util.parse_flags(unpack(args)) }
  51. local flags = table.remove(nonflags, 1)
  52. if flags.ERROR then
  53. die(flags.ERROR.." See --help.")
  54. end
  55. if flags["from"] then flags["server"] = flags["from"] end
  56. if flags["only-from"] then flags["only-server"] = flags["only-from"] end
  57. if flags["only-sources-from"] then flags["only-sources"] = flags["only-sources-from"] end
  58. if flags["to"] then flags["tree"] = flags["to"] end
  59. if flags["nodeps"] then
  60. flags["deps-mode"] = "none"
  61. end
  62. cfg.flags = flags
  63. local command
  64. if flags["verbose"] then -- setting it in the config file will kick-in earlier in the process
  65. cfg.verbose = true
  66. fs.verbose()
  67. end
  68. if flags["timeout"] then -- setting it in the config file will kick-in earlier in the process
  69. local timeout = tonumber(flags["timeout"])
  70. if timeout then
  71. cfg.connection_timeout = timeout
  72. else
  73. die "Argument error: --timeout expects a numeric argument."
  74. end
  75. end
  76. if flags["version"] then
  77. util.printout(program.." "..cfg.program_version)
  78. util.printout(program_description)
  79. util.printout()
  80. os.exit(cfg.errorcodes.OK)
  81. elseif flags["help"] or #nonflags == 0 then
  82. command = "help"
  83. else
  84. command = table.remove(nonflags, 1)
  85. end
  86. command = command:gsub("-", "_")
  87. if cfg.local_by_default then
  88. flags["local"] = true
  89. end
  90. if flags["deps-mode"] and not deps.check_deps_mode_flag(flags["deps-mode"]) then
  91. die("Invalid entry for --deps-mode.")
  92. end
  93. if flags["branch"] then
  94. cfg.branch = flags["branch"]
  95. end
  96. if flags["tree"] then
  97. local named = false
  98. for _, tree in ipairs(cfg.rocks_trees) do
  99. if type(tree) == "table" and flags["tree"] == tree.name then
  100. if not tree.root then
  101. die("Configuration error: tree '"..tree.name.."' has no 'root' field.")
  102. end
  103. replace_tree(flags, tree.root)
  104. named = true
  105. break
  106. end
  107. end
  108. if not named then
  109. local root_dir = fs.absolute_name(flags["tree"])
  110. replace_tree(flags, root_dir)
  111. end
  112. elseif flags["local"] then
  113. if not cfg.home_tree then
  114. die("The --local flag is meant for operating in a user's home directory.\n"..
  115. "You are running as a superuser, which is intended for system-wide operation.\n"..
  116. "To force using the superuser's home, use --tree explicitly.")
  117. end
  118. replace_tree(flags, cfg.home_tree)
  119. else
  120. local trees = cfg.rocks_trees
  121. path.use_tree(trees[#trees])
  122. end
  123. if type(cfg.root_dir) == "string" then
  124. cfg.root_dir = cfg.root_dir:gsub("/+$", "")
  125. else
  126. cfg.root_dir.root = cfg.root_dir.root:gsub("/+$", "")
  127. end
  128. cfg.rocks_dir = cfg.rocks_dir:gsub("/+$", "")
  129. cfg.deploy_bin_dir = cfg.deploy_bin_dir:gsub("/+$", "")
  130. cfg.deploy_lua_dir = cfg.deploy_lua_dir:gsub("/+$", "")
  131. cfg.deploy_lib_dir = cfg.deploy_lib_dir:gsub("/+$", "")
  132. cfg.variables.ROCKS_TREE = cfg.rocks_dir
  133. cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir
  134. if flags["server"] then
  135. local protocol, path = dir.split_url(flags["server"])
  136. table.insert(cfg.rocks_servers, 1, protocol.."://"..path)
  137. end
  138. if flags["only-server"] then
  139. cfg.rocks_servers = { flags["only-server"] }
  140. end
  141. if flags["only-sources"] then
  142. cfg.only_sources_from = flags["only-sources"]
  143. end
  144. if command ~= "help" then
  145. for k, v in pairs(cmdline_vars) do
  146. cfg.variables[k] = v
  147. end
  148. end
  149. if not fs.current_dir() or fs.current_dir() == "" then
  150. die("Current directory does not exist. Please run LuaRocks from an existing directory.")
  151. end
  152. if commands[command] then
  153. local cmd = require(commands[command])
  154. local xp, ok, err, exitcode = xpcall(function() return cmd.command(flags, unpack(nonflags)) end, function(err)
  155. die(debug.traceback("LuaRocks "..cfg.program_version
  156. .." bug (please report at https://github.com/keplerproject/luarocks/issues).\n"
  157. ..err, 2), cfg.errorcodes.CRASH)
  158. end)
  159. if xp and (not ok) then
  160. die(err, exitcode)
  161. end
  162. else
  163. die("Unknown command: "..command)
  164. end
  165. util.run_scheduled_functions()
  166. end
  167. return command_line