2021-01-12 23:11:00 +11:00
-- Copyright (C) 2018-2021 by KittenOS NEO contributors
--
-- Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-- THIS SOFTWARE.
2018-03-19 10:10:54 +11:00
-- app-claw: Package manager.
2018-06-12 10:27:26 +10:00
local ldrPkg , _ , tgtPkg = ...
2018-03-28 00:40:05 +11:00
-- libs & such
local event = require ( " event " ) ( neo )
2018-06-12 10:27:26 +10:00
local neoux = require ( " neoux " ) ( event , neo )
2018-03-28 00:40:05 +11:00
2018-03-19 10:10:54 +11:00
local primaryINet = neo.requestAccess ( " c.internet " )
if primaryINet then primaryINet = primaryINet.list ( ) ( ) end
--
2018-06-12 10:27:26 +10:00
local function readFile ( src , url , ocb )
local buf = " "
local function cb ( data )
if not data then
ocb ( buf )
else
buf = buf .. data
buf = buf : gsub ( " [^ \n ]* \n " , function ( t )
ocb ( t : sub ( 1 , - 2 ) )
return " "
end )
2018-03-28 00:40:05 +11:00
end
2018-06-12 10:27:26 +10:00
end
if type ( src ) == " string " then
assert ( primaryINet , " no internet " )
local req , err = primaryINet.request ( src .. url )
assert ( req , err )
-- OpenComputers#535
req.finishConnect ( )
while true do
local n , n2 = req.read ( neo.readBufSize )
cb ( n )
if not n then
req.close ( )
if n2 then
error ( n2 )
else
cb ( nil )
break
end
2018-03-19 10:10:54 +11:00
else
2018-06-12 10:27:26 +10:00
if n == " " then
-- slightly dangerous, but what can we do?
pcall ( event.sleepTo , os.uptime ( ) + 0.05 )
end
2018-03-19 10:10:54 +11:00
end
2018-06-12 10:27:26 +10:00
end
else
if url == " data/app-claw/local.c2l " then
for _ , v in ipairs ( src.list ( " data/app-claw/ " ) ) do
ocb ( v )
2018-03-19 10:10:54 +11:00
end
2018-06-12 10:27:26 +10:00
return
2018-03-19 10:10:54 +11:00
end
2018-06-12 10:27:26 +10:00
local h , e = src.open ( url , " rb " )
assert ( h , e )
repeat
local c = src.read ( h , neo.readBufSize )
cb ( c )
until not c
src.close ( h )
2018-03-19 10:10:54 +11:00
end
end
2018-06-12 10:27:26 +10:00
-- Sources
local sources = { }
local sourceList = { }
-- Use all non-primary filesystems
local disks = neo.requireAccess ( " c.filesystem " , " searching disks for packages " )
local primaryDisk = disks.primary
for pass = 1 , 3 do
for v in disks.list ( ) do
local nam = nil
if v == primaryDisk then
nam = ( pass == 1 ) and " local "
elseif v == disks.temporary then
nam = ( pass == 2 ) and " ramfs "
elseif pass == 3 then
nam = v.address
end
if nam then
sources [ nam ] = v
table.insert ( sourceList , nam )
2018-03-19 10:10:54 +11:00
end
end
end
2018-06-12 10:27:26 +10:00
-- No longer needed
disks = nil
if primaryINet then
2018-07-28 23:53:04 +10:00
sources [ " inet " ] = " http://20kdc.duckdns.org/neo/ "
2018-06-12 10:27:26 +10:00
table.insert ( sourceList , " inet " )
2018-03-28 00:40:05 +11:00
end
2018-06-12 10:27:26 +10:00
-- List scanning for package window
local function scanList ( content )
local lst = { }
local lst2 = { }
for k , v in pairs ( sources ) do
local ok , err = pcall ( readFile , v , " data/app-claw/local.c2l " , function ( l )
if l : sub ( - 4 ) == " .c2p " then
local lt , ltv = l : sub ( 1 , - 5 )
ltv = lt : match ( " %.[0-9]+$ " )
if ltv and l : find ( content , 1 , true ) then
lt = lt : sub ( 1 , - ( # ltv + 1 ) )
lst2 [ lt ] = true
end
end
end )
if ( not ok ) and ( ( k == " inet " ) or ( k == " local " ) ) then
neoux.startDialog ( tostring ( err ) , k )
end
2018-03-19 10:10:54 +11:00
end
2018-06-12 10:27:26 +10:00
for k , v in pairs ( lst2 ) do
table.insert ( lst , k )
end
table.sort ( lst )
return lst
2018-03-19 10:10:54 +11:00
end
2018-03-28 00:40:05 +11:00
-- Beginning Of The App (well, the actual one)
local genCurrent , genPrimary , genPackage , primaryWindow
2018-04-29 06:27:45 +10:00
local running = true
2018-03-28 00:40:05 +11:00
-- primary
local primarySearchTx = " "
local primaryPage = 1
2018-06-12 10:27:26 +10:00
local primaryList = scanList ( " " )
2018-03-30 03:31:51 +11:00
local primaryNextMinus = false
2018-03-28 00:40:05 +11:00
-- package
local packageLock = nil
local packageId = " FIXME "
2018-06-12 10:27:26 +10:00
local function describe ( pkgs )
local lowestV , highestV , myV = { } , { } , { }
for pk , pv in ipairs ( pkgs ) do
lowestV [ pk ] = math.huge
highestV [ pk ] = - math.huge
end
for k , v in pairs ( sources ) do
pcall ( readFile , v , " data/app-claw/local.c2l " , function ( l )
local lp = l : match ( " %.[0-9]+%.c2p$ " )
for pk , pkg in ipairs ( pkgs ) do
if lp and l : sub ( 1 , - ( # lp + 1 ) ) == pkg then
local v = tonumber ( lp : sub ( 2 , - 5 ) )
if k == " local " then
myV [ pk ] = v
end
lowestV [ pk ] = math.min ( lowestV [ pk ] , v )
highestV [ pk ] = math.max ( highestV [ pk ] , v )
end
end
end )
end
for pk , pkg in ipairs ( pkgs ) do
if lowestV [ pk ] == math.huge then
pkgs [ pk ] = pkg .. " (ERR) "
elseif myV [ pk ] then
if highestV [ pk ] > myV [ pk ] then
pkgs [ pk ] = pkg .. " [v " .. myV [ pk ] .. " !] "
elseif lowestV [ pk ] < myV [ pk ] then
pkgs [ pk ] = pkg .. " (v " .. myV [ pk ] .. " ) R< "
else
pkgs [ pk ] = pkg .. " (v " .. myV [ pk ] .. " ) "
end
2018-03-19 10:10:54 +11:00
end
end
end
2018-03-28 00:40:05 +11:00
local function primaryWindowRegenCore ( )
2018-03-30 03:31:51 +11:00
local gen , gens = genCurrent ( )
2018-06-12 10:27:26 +10:00
return 25 , 14 , " claw " , neoux.tcwindow ( 25 , 14 , gen , function ( w )
2018-03-28 00:40:05 +11:00
w.close ( )
2018-04-29 06:27:45 +10:00
running = false
2018-03-30 03:31:51 +11:00
end , 0xFF8F00 , 0 , gens )
2018-03-19 10:10:54 +11:00
end
2018-03-28 00:40:05 +11:00
local function primaryWindowRegen ( )
2018-03-30 03:31:51 +11:00
primaryWindow.reset ( primaryWindowRegenCore ( ) )
2018-03-19 10:10:54 +11:00
end
2018-03-28 00:40:05 +11:00
-- Sections
function genPrimary ( )
2018-03-30 03:31:51 +11:00
local minus = ( primaryNextMinus and 3 ) or nil
primaryNextMinus = false
2018-06-12 10:27:26 +10:00
local pgs = 12
2018-03-28 00:40:05 +11:00
local pages = math.ceil ( # primaryList / pgs )
2018-03-19 10:10:54 +11:00
local elems = {
2018-03-28 00:40:05 +11:00
neoux.tcbutton ( 23 , 1 , " + " , function ( w )
if primaryPage < pages then
primaryPage = primaryPage + 1
2018-03-19 10:10:54 +11:00
primaryWindowRegen ( )
end
end ) ,
2018-03-28 00:40:05 +11:00
neoux.tcrawview ( 4 , 1 , { neoux.pad ( primaryPage .. " / " .. pages , 19 , true , true ) } ) ,
2018-03-19 10:10:54 +11:00
neoux.tcbutton ( 1 , 1 , " - " , function ( w )
2018-03-28 00:40:05 +11:00
if primaryPage > 1 then
2018-03-30 03:31:51 +11:00
primaryNextMinus = true
2018-03-28 00:40:05 +11:00
primaryPage = primaryPage - 1
2018-03-19 10:10:54 +11:00
primaryWindowRegen ( )
end
end )
}
2018-03-28 00:40:05 +11:00
local base = ( primaryPage - 1 ) * pgs
2018-06-12 10:27:26 +10:00
local pkgs = { }
for i = 1 , pgs do
local ent = primaryList [ base + i ]
if ent then
pkgs [ i ] = ent
end
end
describe ( pkgs )
2018-03-28 00:40:05 +11:00
for i = 1 , pgs do
local ent = primaryList [ base + i ]
2018-03-19 10:10:54 +11:00
if ent then
2018-06-12 10:27:26 +10:00
local enttx = pkgs [ i ]
2018-03-19 10:10:54 +11:00
table.insert ( elems , neoux.tcbutton ( 1 , i + 1 , unicode.safeTextFormat ( enttx ) , function ( w )
2018-04-29 06:27:45 +10:00
-- FREE UP MEMORY NOW
elems = { }
2018-06-12 10:27:26 +10:00
w.reset ( 25 , 14 , " claw " , function ( ev )
2018-04-29 06:27:45 +10:00
if ev == " close " then
w.close ( )
running = false
end
end )
2018-03-28 00:40:05 +11:00
packageId = ent
genCurrent = genPackage
primaryWindowRegen ( )
2018-03-19 10:10:54 +11:00
end ) )
end
end
2018-06-12 10:27:26 +10:00
table.insert ( elems , neoux.tcfield ( 1 , 14 , 16 , function ( s )
2018-03-28 00:40:05 +11:00
if s then primarySearchTx = s end
return primarySearchTx
2018-03-19 10:10:54 +11:00
end ) )
2018-06-12 10:27:26 +10:00
table.insert ( elems , neoux.tcbutton ( 17 , 14 , " Search! " , function ( w )
2018-03-28 00:40:05 +11:00
primaryPage = 1
2018-06-12 10:27:26 +10:00
primaryList = scanList ( primarySearchTx )
2018-03-19 10:10:54 +11:00
primaryWindowRegen ( )
end ) )
2018-03-30 03:31:51 +11:00
return elems , minus
2018-03-19 10:10:54 +11:00
end
2018-03-28 00:40:05 +11:00
--
local function packageGetBB ( src , lclI , srcI , srcW )
local buttons = { }
if srcI and srcW then
table.insert ( buttons , {
" Del " ,
2018-06-12 10:27:26 +10:00
function ( w )
w.close ( )
running = false
2018-06-13 06:45:40 +10:00
neo.executeAsync ( " svc-app-claw-worker " , sources [ src ] , packageId , nil , src == " local " , primaryINet )
2018-03-28 00:40:05 +11:00
end
} )
end
2018-06-12 10:27:26 +10:00
if srcI and ( ( not lclI ) or ( lclI < srcI ) ) then
2018-03-28 00:40:05 +11:00
table.insert ( buttons , {
" Get " ,
2018-06-12 10:27:26 +10:00
function ( w )
w.close ( )
running = false
2018-06-13 06:45:40 +10:00
neo.executeAsync ( " svc-app-claw-worker " , sources [ " local " ] , packageId , sources [ src ] , true , primaryINet )
2018-03-28 00:40:05 +11:00
end
} )
end
if srcW and lclI and not srcI then
table.insert ( buttons , {
" All " ,
2018-06-12 10:27:26 +10:00
function ( w )
w.close ( )
running = false
2018-06-13 06:45:40 +10:00
neo.executeAsync ( " svc-app-claw-worker " , sources [ src ] , packageId , sources [ " local " ] , true , primaryINet )
2018-03-28 00:40:05 +11:00
end
} )
table.insert ( buttons , {
" Put " ,
2018-06-12 10:27:26 +10:00
function ( w )
w.close ( )
running = false
2018-06-13 06:45:40 +10:00
neo.executeAsync ( " svc-app-claw-worker " , sources [ src ] , packageId , sources [ " local " ] , false , primaryINet )
2018-03-28 00:40:05 +11:00
end
} )
end
return buttons
end
function genPackage ( )
if packageLock then
return { neoux.tcrawview ( 1 , 1 , neoux.fmtText ( unicode.safeTextFormat ( packageId .. " \n " .. packageLock ) , 25 ) ) }
end
-- concept:
-- mtd <back>
-- Multi-Track Drifting
--
-- local v20 <del> <run>
-- inet v21 <pull>
-- dir v22 <pull> <push>
-- crockett <push>
2018-06-12 10:27:26 +10:00
local sourceVers = { }
local c2pSrc = " local "
local c2pVer = - 1
for k , v in pairs ( sources ) do
local ok , err = pcall ( readFile , v , " data/app-claw/local.c2l " , function ( l )
local lp = l : match ( " %.[0-9]+%.c2p$ " )
if lp and l : sub ( 1 , - ( # lp + 1 ) ) == packageId then
sourceVers [ k ] = tonumber ( lp : sub ( 2 , - 5 ) )
if c2pVer < sourceVers [ k ] then
c2pSrc = k
c2pVer = sourceVers [ k ]
end
end
end )
end
if sourceVers [ " local " ] then
c2pSrc = " local "
c2pVer = sourceVers [ " local " ]
end
local text = " "
local ok = pcall ( readFile , sources [ c2pSrc ] , " data/app-claw/ " .. packageId .. " . " .. c2pVer .. " .c2p " , function ( l )
text = text .. l .. " \n "
end )
if not ok then
text = packageId .. " \n Unable to read v " .. c2pVer .. " c2p from: " .. c2pSrc
end
2018-03-28 00:40:05 +11:00
local elems = {
2018-06-12 10:27:26 +10:00
neoux.tcrawview ( 1 , 1 , neoux.fmtText ( unicode.safeTextFormat ( text ) , 25 ) ) ,
2018-03-28 00:40:05 +11:00
neoux.tcbutton ( 20 , 1 , " Back " , function ( )
if packageLock then return end
genCurrent = genPrimary
primaryWindowRegen ( )
end )
}
2018-06-12 10:27:26 +10:00
for k , v in ipairs ( sourceList ) do
local row = 14 + k - # sourceList
2018-03-28 00:40:05 +11:00
local pfx = " "
2018-06-12 10:27:26 +10:00
if sourceVers [ v ] then
pfx = " v " .. string.format ( " %04i " , sourceVers [ v ] ) .. " "
2018-03-28 00:40:05 +11:00
end
2018-06-12 10:27:26 +10:00
table.insert ( elems , neoux.tcrawview ( 1 , row , { neoux.pad ( pfx .. v , 14 , false , true ) } ) )
2018-03-28 00:40:05 +11:00
local col = 26
2018-06-12 10:27:26 +10:00
local srcW = type ( sources [ v ] ) ~= " string "
for _ , bv in ipairs ( packageGetBB ( v , sourceVers [ " local " ] , sourceVers [ v ] , srcW ) ) do
2018-03-28 00:40:05 +11:00
local b = neoux.tcbutton ( col , row , bv [ 1 ] , bv [ 2 ] )
col = col - b.w
b.x = col
table.insert ( elems , b )
end
end
return elems
end
--
2018-06-12 10:27:26 +10:00
if ldrPkg == " svc-app-claw-worker " and tgtPkg then
packageId = tgtPkg
genCurrent = genPackage
else
genCurrent = genPrimary
end
2018-03-30 03:31:51 +11:00
primaryWindow = neoux.create ( primaryWindowRegenCore ( ) )
2018-03-19 10:10:54 +11:00
2018-04-29 06:27:45 +10:00
while running do
2018-03-19 10:10:54 +11:00
event.pull ( )
end