PageRenderTime 39ms CodeModel.GetById 21ms app.highlight 12ms RepoModel.GetById 2ms app.codeStats 0ms

/src/luarocks/command_line.lua

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