Merge branch 'master-MC1.7.10' of github.com:MightyPirates/OpenComputers into master-MC1.8

This commit is contained in:
Florian Nücke 2015-05-01 10:47:51 +02:00
commit 6b80b75fd3
8 changed files with 87 additions and 39 deletions

View File

@ -7,6 +7,8 @@ if #args < 2 then
io.write(" -i: prompt before overwrite (overrides -n option).\n") io.write(" -i: prompt before overwrite (overrides -n option).\n")
io.write(" -n: do not overwrite an existing file.\n") io.write(" -n: do not overwrite an existing file.\n")
io.write(" -r: copy directories recursively.\n") io.write(" -r: copy directories recursively.\n")
io.write(" -u: copy only when the SOURCE file differs from the destination\n")
io.write(" file or when the destination file is missing.\n")
io.write(" -v: verbose output.") io.write(" -v: verbose output.")
return return
end end
@ -19,7 +21,7 @@ local to = shell.resolve(args[#args])
local function status(from, to) local function status(from, to)
if options.v then if options.v then
print(from .. " -> " .. to) io.write(from .. " -> " .. to .. "\n")
end end
os.sleep(0) -- allow interrupting os.sleep(0) -- allow interrupting
end end
@ -27,9 +29,33 @@ end
local result, reason local result, reason
local function prompt(message) local function prompt(message)
io.write(message .. " ") io.write(message .. " [Y/n]\n")
local result = io.read() local result = io.read()
return result and result:sub(1, 1):lower() == "y" return result and (result == "" or result:sub(1, 1):lower() == "y")
end
local function areEqual(path1, path2)
local f1 = io.open(path1, "rb")
if not f1 then
return nil, "could not open `" .. path1 .. "' for update test"
end
local f2 = io.open(path2, "rb")
if not f2 then
f1:close()
return nil, "could not open `" .. path2 .. "' for update test"
end
local result = true
local chunkSize = 4 * 1024
repeat
local s1, s2 = f1:read(chunkSize), f2:read(chunkSize)
if s1 ~= s2 then
result = false
break
end
until not s1 or not s2
f1:close()
f2:close()
return result
end end
local function recurse(fromPath, toPath) local function recurse(fromPath, toPath)
@ -70,6 +96,11 @@ local function recurse(fromPath, toPath)
return nil, "cannot overwrite directory `" .. toPath .. "' with non-directory" return nil, "cannot overwrite directory `" .. toPath .. "' with non-directory"
end end
else else
if options.u then
if areEqual(fromPath, toPath) then
return true
end
end
if options.i then if options.i then
if not prompt("overwrite `" .. toPath .. "'?") then if not prompt("overwrite `" .. toPath .. "'?") then
return true return true

View File

@ -1,22 +1,24 @@
local component = require("component") local component = require("component")
local computer = require("computer") local computer = require("computer")
local event = require("event") local event = require("event")
local filesystem = require("filesystem")
local unicode = require("unicode") local unicode = require("unicode")
local shell = require("shell") local shell = require("shell")
local args, options = shell.parse(...) local args, options = shell.parse(...)
local fromAddress = options.from and component.get(options.from) or filesystem.get(os.getenv("_")).address
local candidates = {} local candidates = {}
for address in component.list("filesystem") do for address in component.list("filesystem") do
local dev = component.proxy(address) local dev = component.proxy(address)
if not dev.isReadOnly() and dev.address ~= computer.tmpAddress() then if not dev.isReadOnly() and dev.address ~= computer.tmpAddress() and dev.address ~= fromAddress then
table.insert(candidates, dev) table.insert(candidates, dev)
end end
end end
if #candidates == 0 then if #candidates == 0 then
print("No writable disks found, aborting.") io.write("No writable disks found, aborting.\n")
return os.exit()
end end
for i = 1, #candidates do for i = 1, #candidates do
@ -26,45 +28,53 @@ for i = 1, #candidates do
else else
label = candidates[i].address label = candidates[i].address
end end
print(i .. ") " .. label) io.write(i .. ") " .. label .. "\n")
end end
print("To select the device to install to, please enter a number between 1 and " .. #candidates .. ".") io.write("To select the device to install to, please enter a number between 1 and " .. #candidates .. ".\n")
print("Press 'q' to cancel the installation.") io.write("Press 'q' to cancel the installation.\n")
local choice local choice
while not choice do while not choice do
result = io.read() result = io.read()
if result:sub(1, 1):lower() == "q" then if result:sub(1, 1):lower() == "q" then
return os.exit()
end end
local number = tonumber(result) local number = tonumber(result)
if number and number > 0 and number <= #candidates then if number and number > 0 and number <= #candidates then
choice = candidates[number] choice = candidates[number]
else else
print("Invalid input, please try again.") io.write("Invalid input, please try again.\n")
end
end
local function findMount(address)
for fs, path in filesystem.mounts() do
if fs.address == component.get(address) then
return path
end
end end
end end
candidates = nil
local name = options.name or "OpenOS" local name = options.name or "OpenOS"
print("Installing " .. name .." to device " .. (choice.getLabel() or choice.address)) io.write("Installing " .. name .." to device " .. (choice.getLabel() or choice.address) .. "\n")
os.sleep(0.25) os.sleep(0.25)
local origin = options.from and options.from:sub(1,3) or computer.getBootAddress():sub(1, 3) local cpPath = filesystem.concat(findMount(filesystem.get(os.getenv("_")).address), "bin/cp")
local fromDir = options.fromDir or "/" local cpOptions = "-vr" .. (options.u and "ui " or "")
local mnt = choice.address:sub(1, 3) local cpSource = filesystem.concat(findMount(fromAddress), options.fromDir or "/", "*")
local result, reason = os.execute("/bin/cp -vr /mnt/" .. origin .. fromDir .. "* /mnt/" .. mnt .. "/") local cpDest = findMount(choice.address) .. "/"
local result, reason = os.execute(cpPath .. " " .. cpOptions .. " " .. cpSource .. " " .. cpDest)
if not result then if not result then
error(reason, 0) error(reason, 0)
end end
if not options.nolabelset then pcall(choice.setLabel, name) end if not options.nolabelset then pcall(choice.setLabel, name) end
if not options.noreboot then if not options.noreboot then
print("All done! " .. ((not options.noboot) and "Set as boot device and r" or "R") .. "eboot now? [Y/n]") io.write("All done! " .. ((not options.noboot) and "Set as boot device and r" or "R") .. "eboot now? [Y/n]\n")
local result = io.read() local result = io.read()
if not result or result == "" or result:sub(1, 1):lower() == "y" then if not result or result == "" or result:sub(1, 1):lower() == "y" then
if not options.noboot then computer.setBootAddress(choice.address)end if not options.noboot then computer.setBootAddress(choice.address)end
print("\nRebooting now!") io.write("\nRebooting now!\n")
computer.shutdown(true) computer.shutdown(true)
end end
end end
print("Returning to shell.") io.write("Returning to shell.\n")

View File

@ -17,6 +17,9 @@ function memoryStream:close()
end end
function memoryStream:seek() function memoryStream:seek()
if self.closed then
error("attempt to use a closed stream")
end
return nil, "bad file descriptor" return nil, "bad file descriptor"
end end
@ -24,8 +27,9 @@ function memoryStream:read(n)
if self.closed then if self.closed then
if self.buffer == "" and self.redirect.read then if self.buffer == "" and self.redirect.read then
return self.redirect.read:read(n) return self.redirect.read:read(n)
else
error("attempt to use a closed stream")
end end
return nil -- eof
end end
if self.buffer == "" then if self.buffer == "" then
self.args = table.pack(coroutine.yield(table.unpack(self.result))) self.args = table.pack(coroutine.yield(table.unpack(self.result)))
@ -36,19 +40,24 @@ function memoryStream:read(n)
end end
function memoryStream:write(value) function memoryStream:write(value)
local ok if not self.redirect.write and self.closed then
error("attempt to use a closed stream")
end
if self.redirect.write then if self.redirect.write then
ok = self.redirect.write:write(value) self.redirect.write:write(value)
end end
if not self.closed then if not self.closed then
self.buffer = self.buffer .. value self.buffer = self.buffer .. value
self.result = table.pack(coroutine.resume(self.next, table.unpack(self.args))) self.result = table.pack(coroutine.resume(self.next, table.unpack(self.args)))
ok = true if coroutine.status(self.next) == "dead" then
self:close()
end
if not self.result[1] then
error(self.result[2], 0)
end
table.remove(self.result, 1)
end end
if ok then return true
return true
end
return nil, "stream is closed"
end end
function memoryStream.new() function memoryStream.new()
@ -328,16 +337,15 @@ local function execute(env, command, ...)
result = table.pack(coroutine.resume(threads[i], table.unpack(args, 2, args.n))) result = table.pack(coroutine.resume(threads[i], table.unpack(args, 2, args.n)))
if coroutine.status(threads[i]) ~= "dead" then if coroutine.status(threads[i]) ~= "dead" then
args = table.pack(pcall(event.pull, table.unpack(result, 2, result.n))) args = table.pack(pcall(event.pull, table.unpack(result, 2, result.n)))
elseif not args[1] then
args[2] = debug.traceback(threads[i], args[2])
end end
end end
if pipes[i] then if pipes[i] then
pipes[i]:close() pcall(pipes[i].close, pipes[i])
end end
if not result[1] then if not result[1] then
if type(result[2]) == "table" and result[2].reason == "terminated" then if type(result[2]) == "table" and result[2].reason == "terminated" then
if result[2].code then if result[2].code then
result[1] = true
result.n = 1 result.n = 1
else else
result[2] = "terminated" result[2] = "terminated"
@ -473,7 +481,7 @@ if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then
term.write("\n") term.write("\n")
end end
if not result then if not result then
io.stderr:write((tostring(reason) or "unknown error").. "\n") io.stderr:write((reason and tostring(reason) or "unknown error") .. "\n")
end end
end end
end end
@ -491,7 +499,7 @@ elseif #args == 0 and (io.input() ~= io.stdin) then
elseif command ~= "" then elseif command ~= "" then
local result, reason = os.execute(command) local result, reason = os.execute(command)
if not result then if not result then
io.stderr:write((tostring(reason) or "unknown error").. "\n") io.stderr:write((reason and tostring(reason) or "unknown error") .. "\n")
end end
end end
end end

View File

@ -1,7 +1,7 @@
local args = {...} local args = {...}
if #args < 1 then if #args < 1 then
print("Usage: unset <varname>[ <varname2> [...]]") io.write("Usage: unset <varname>[ <varname2> [...]]\n")
else else
for _, k in ipairs(args) do for _, k in ipairs(args) do
os.setenv(k, nil) os.setenv(k, nil)

View File

@ -175,7 +175,7 @@ local function motd()
os.execute("/etc/motd") os.execute("/etc/motd")
else else
f:seek("set", 0) f:seek("set", 0)
print(f:read("*a")) io.write(f:read("*a") .. "\n")
f:close() f:close()
end end
end end
@ -185,7 +185,7 @@ while true do
local result, reason = os.execute(os.getenv("SHELL")) local result, reason = os.execute(os.getenv("SHELL"))
if not result then if not result then
io.stderr:write((tostring(reason) or "unknown error") .. "\n") io.stderr:write((tostring(reason) or "unknown error") .. "\n")
print("Press any key to continue.") io.write("Press any key to continue.\n")
os.sleep(0.5) os.sleep(0.5)
require("event").pull("key") require("event").pull("key")
end end

View File

@ -25,7 +25,7 @@ function buffer.new(mode, stream)
end end
function buffer:close() function buffer:close()
if self.mode.w or self.mode.a then if not self.closed and (self.mode.w or self.mode.a) then
self:flush() self:flush()
end end
self.closed = true self.closed = true

View File

@ -210,7 +210,6 @@ function event.pullFiltered(...)
if not (seconds or filter) or filter == nil or filter(table.unpack(signal, 1, signal.n)) then if not (seconds or filter) or filter == nil or filter(table.unpack(signal, 1, signal.n)) then
return table.unpack(signal, 1, signal.n) return table.unpack(signal, 1, signal.n)
end end
until computer.uptime() >= deadline until computer.uptime() >= deadline
end end

View File

@ -383,7 +383,7 @@ function term.read(history, dobreak, hint, pwchar, filter)
end end
term.setCursorBlink(false) term.setCursorBlink(false)
if term.getCursor() > 1 and dobreak ~= false then if term.getCursor() > 1 and dobreak ~= false then
print() term.write("\n")
end end
end end