199 lines
4.6 KiB
Lua
199 lines
4.6 KiB
Lua
local Ansi = require('ansi')
|
|
local Event = require('event')
|
|
local UI = require('ui')
|
|
local Util = require('util')
|
|
|
|
local colors = _G.colors
|
|
local fs = _G.fs
|
|
local peripheral = _G.peripheral
|
|
|
|
local drives = { }
|
|
peripheral.find('drive', function(n, v)
|
|
if not drives.left then
|
|
drives.left = Util.shallowCopy(v)
|
|
drives.left.name = n
|
|
else
|
|
drives.right = Util.shallowCopy(v)
|
|
drives.right.name = n
|
|
end
|
|
end)
|
|
|
|
if not (drives.left and drives.right) then
|
|
error('Two drives are required')
|
|
end
|
|
|
|
local COPY_LEFT = 1
|
|
local COPY_RIGHT = 2
|
|
local directions = {
|
|
[ COPY_LEFT ] = { text = '-->>' },
|
|
[ COPY_RIGHT ] = { text = '<<--' },
|
|
}
|
|
local copyDir = COPY_LEFT
|
|
|
|
local page = UI.Page {
|
|
linfo = UI.Window {
|
|
x = 2, y = 2, ey = 5, width = 18,
|
|
},
|
|
rinfo = UI.Window {
|
|
x = -19, y = 2, ey = 5, width = 18,
|
|
},
|
|
dir = UI.Button {
|
|
x = 17, y = 7, width = 6,
|
|
event = 'change_dir',
|
|
},
|
|
progress = UI.ProgressBar {
|
|
x = 2, ex = -2, y = -4,
|
|
backgroundColor = colors.black,
|
|
},
|
|
copyButton = UI.Button {
|
|
x = -7, y = -2,
|
|
text = 'Copy',
|
|
event = 'copy',
|
|
inactive = true,
|
|
},
|
|
warning = UI.Text {
|
|
x = 2, ex = -9, y = -2,
|
|
textColor = colors.orange,
|
|
},
|
|
notification = UI.Notification { },
|
|
}
|
|
|
|
function page:enable()
|
|
Util.merge(self.dir, directions[copyDir])
|
|
UI.Page.enable(self)
|
|
end
|
|
|
|
local function isValid(drive)
|
|
return drive.isDiskPresent() and drive.getMountPath()
|
|
end
|
|
|
|
local function needsLabel(drive)
|
|
return drive.isDiskPresent() and not drive.getMountPath() and not drive.getAudioTitle()
|
|
end
|
|
|
|
function page:drawInfo(drive, textArea)
|
|
local function getLabel()
|
|
return not drive.isDiskPresent() and 'empty' or
|
|
not drive.getMountPath() and 'invalid' or
|
|
drive.getDiskLabel() or 'unlabeled'
|
|
end
|
|
|
|
local function getUsed()
|
|
return isValid(drive) and fs.getSize(drive.getMountPath(), true) or 0
|
|
end
|
|
|
|
local function getFree()
|
|
return isValid(drive) and fs.getFreeSpace(drive.getMountPath()) or 0
|
|
end
|
|
|
|
textArea:setCursorPos(1, 1)
|
|
textArea:print(string.format('Drive: %s%s%s\nLabel: %s%s%s\nUsed: %s%s%s\nFree: %s%s%s',
|
|
Ansi.yellow, drive.name, Ansi.reset,
|
|
isValid(drive) and Ansi.yellow or Ansi.orange, getLabel():sub(1, 10), Ansi.reset,
|
|
Ansi.yellow, Util.toBytes(getUsed()), Ansi.reset,
|
|
Ansi.yellow, Util.toBytes(getFree()), Ansi.reset))
|
|
end
|
|
|
|
function page:scan()
|
|
local showWarning = needsLabel(drives.left) or needsLabel(drives.right)
|
|
local valid = isValid(drives.left) and isValid(drives.right)
|
|
|
|
self.warning.value = showWarning and 'Computers must be labeled'
|
|
self.copyButton.inactive = not valid
|
|
|
|
self:draw()
|
|
self.progress:centeredWrite(1, 'Analyzing Disks..')
|
|
self.progress:sync()
|
|
|
|
self:drawInfo(drives.left, self.linfo)
|
|
self:drawInfo(drives.right, self.rinfo)
|
|
|
|
self.progress:clear()
|
|
end
|
|
|
|
function page:copy(sdrive, tdrive)
|
|
local totalFiles = 0
|
|
local throttle = Util.throttle()
|
|
|
|
local function countFiles(source, target)
|
|
if fs.isDir(source) then
|
|
for _,f in pairs(fs.list(source)) do
|
|
countFiles(fs.combine(source, f), fs.combine(target, f))
|
|
end
|
|
else
|
|
totalFiles = totalFiles + 1
|
|
end
|
|
throttle()
|
|
end
|
|
|
|
local copied = 0
|
|
local function rawCopy(source, target)
|
|
if fs.isDir(source) then
|
|
if not fs.exists(target) then
|
|
fs.makeDir(target)
|
|
end
|
|
for _,f in pairs(fs.list(source)) do
|
|
rawCopy(fs.combine(source, f), fs.combine(target, f))
|
|
end
|
|
|
|
else
|
|
if fs.exists(target) then
|
|
fs.delete(target)
|
|
end
|
|
|
|
fs.copy(source, target)
|
|
copied = copied + 1
|
|
self.progress.value = copied * 100 / totalFiles
|
|
self.progress:draw()
|
|
self.progress:sync()
|
|
end
|
|
throttle()
|
|
end
|
|
|
|
self.progress:centeredWrite(1, 'Computing..')
|
|
self.progress:sync()
|
|
countFiles(sdrive.getMountPath(), tdrive.getMountPath())
|
|
|
|
self.progress:clear()
|
|
rawCopy(sdrive.getMountPath(), tdrive.getMountPath())
|
|
self.progress:centeredWrite(1, 'Copy Complete', colors.lime, colors.black)
|
|
self.progress:sync()
|
|
|
|
self.progress.value = 0
|
|
self.progress:clear()
|
|
|
|
self:scan()
|
|
end
|
|
|
|
function page:eventHandler(event)
|
|
if event.type == 'change_dir' then
|
|
copyDir = (copyDir) % 2 + 1
|
|
Util.merge(self.dir, directions[copyDir])
|
|
self.dir:draw()
|
|
|
|
elseif event.type == 'copy' then
|
|
if copyDir == COPY_LEFT then
|
|
self:copy(drives.left, drives.right)
|
|
else
|
|
self:copy(drives.right, drives.left)
|
|
end
|
|
|
|
else
|
|
return UI.Page.eventHandler(self, event)
|
|
end
|
|
return true
|
|
end
|
|
|
|
Event.on({ 'disk', 'disk_eject' }, function()
|
|
page:scan()
|
|
page:sync()
|
|
end)
|
|
|
|
Event.onTimeout(.2, function()
|
|
page:scan()
|
|
page:sync()
|
|
end)
|
|
|
|
UI:setPage(page)
|
|
UI:pullEvents()
|