This cartridge is an installer and uninstaller for a new globally-available command: 'yotta'.
Installation
Initial Installation:
load #yotta
in your Picotron terminal- Ctrl+R to run installer cartridge
- Press X to install
Upgrade Installation from v1.0:
yotta util install #yotta
in your Picotron terminalyotta version
in your Picotron terminal
You should see "yotta version v1.1"
This 'version' command will also migrate the yotta installation files to clean up a little bit. It will move the global yottafile into /appdata/yotta instead of /appdata/system, and it will clean up some of the new CRC verification files that got installed that the new version will handle better behind-the-scenes.
Usage
usage: yotta <commands> commands: version - tell you what version yotta is init - initialize a yottafile for the current directory list - list the current dependencies -v - verbose: list all tracked files under each dependency add <cart> - add a cart ref as dependency (but don't add/remove anything yet) remove <cart> - remove a cart ref as dependency (but don't add/remove anythin yet) apply - make the current directory match a yottafile (this is what actually adds and removes files!) force - this is an apply that will reinstall every dep (for updates?) util install [options] <cart> - globally install utility cart ref by default, it will make a backup in event of a file conflict (file.txt -> file.txt.bak) then install. -g - be gentle. don't install if a file conflict occurs, just move on to install non-conflicting files. -f - be forceful. just overwrite if a file conflict occurs. util uninstall <cart> - globally uninstall utility cart ref util update <cart> - update a globally installed ccart ref util list - list all tracked util cart refs and their files |
The yotta command seems complicated but it's pretty simple if you've ever used dependency managers or package managers on other systems or for other programming languages. I'll outline its two major functions separately.
Yotta as a dependency manager
> cd /ram/cart
> yotta init
> yotta add #bbs_id /my_libs/library.p64
> yotta apply
- In your lua,
include "./lib/bbs_id/main.lua"
andinclude "./lib/library/main.lua"
- Done!
Let's say you've got your cartridge, and you'd like to use a library that exists on the BBS that is compatible with yotta. Or... let's say you have some yotta-compatible libraries on your system that you've written or downloaded and you'd like to use their features in your current cartridge. Or both!
Sit your terminal in /ram/cart
and prepare the cartridge for use with yotta: yotta init
. This will create a /ram/cart/lib
directory, and a /ram/cart/lib/yottafile.pod
file to track dependancies and what dependancies own what files.
Now, to add a dependency, you need to know where it lives. If it's on the BBS, the library cartridge has a BBS ID, and you can supply that like you would with the 'load' command: yotta add #bbs_id
. If your dependency lives in a file on your Picotron, you can specify the path: yotta add /my_libs/library.p64
. This will track the dependency by adding it to the yottafile, but it won't immediately install it. You can specify multiple packages at once from mixed sources (like yotta add #bbs_id /my_libs/library.p64
.)
When you're ready to install the dependencies into your cart's lib/
folder, run yotta apply
. It will fetch the BBS carts and copy the filesystem carts and unpack each of their exports/
folders into named directories in libs/
. For example, using the above two sources we added, you could expect to see something in your cart like libs/bbs_id/main.lua
and libs/library/main.lua
. Everything present in the target dependency cart's exports folder will be copied into this lib/[name] directory (except for .map, .sfx, and .gfx files).
If a target cartridge's export folder contains .map, .sfx, or .gfx files, they will be copied into your cartridge's map/, sfx/, and gfx/ directories, named [library_name]_[exported_filename].[ext]
. They will still be tracked by yotta, so if you remove the dependency and do a yotta apply
, it will remove them cleanly.
If your dependency targets update somehow, you can use yotta force
to force it to reacquire all dependencies instead of simply passing over already-installed packages.
If you decide you no longer need a package, you can remove it nearly the same way you add it: yotta remove #bbs_id
. Then, the next yotta apply
will identify this and remove lib/bbs_id
from your cart, and delete any sfx/gfx/map files that were added by it. It won't remove the includes from your lua code - that's up to you!
Yotta as a package manager
> yotta util install /my_utils/cool_util.p64 #bbs_system_package
- Done!
- Wait I want one of them gone, it sucks!
> yotta util uninstall #bbs_system_package
- Done!
Let's say you see a cool yotta-compatible system package like a new command-line utility (like 'new' or 'merge' ;) ) on the BBS, or let's say you've written a yotta-compatible cartridge containing your utility. Or both!
Grab your terminal, its location doesn't matter. If it's on the BBS, the package cartridge has a BBS ID, and you can supply that like you would with the 'load' command: yotta util install #bbs_system_package
. If your dependency lives in a file on your Picotron, you can specify the path: yotta util install /my_utils/cool_util.p64
. This will track the dependency by adding it to the system yottafile at /appdata/system/global_yottafile.pod
, and will immediately install it. You can specify multiple packages at once from mixed sources, also (like yotta util install /my_utils/cool_util.p64 #bbs_system_package
.)
If you decide you no longer want or need a package, you can remove it nearly the same way you add it: yotta util uninstall /my_utils/cool_util.p64
. It will be immediately uninstalled, but it won't remove any files created by the utility or whatever - only what was installed originally. If it leaves empty directories after it's done removing files, it will clean those up too.
Building libraries for use with yotta
It's simple! Place whatever you'd like to be available in your end-user cart's lib/your_package_name
directory into your cart's exports/
folder. Make it if it doesn't exist. If you add .sfx, .map, or .gfx files, they will be copied into your end-users sfx/, map/, and gfx/ folders, named [your_package_name]_[filename_in_your_exports].[ext]
.
If your cartridge does nothing else other than offer your library to folks, then you're welcome to use my library container utility to help inform users that this is not a 'runnable' cartridge and is instead a kind of 'resource' cartridge. It gives them the ability to view the files if they run it, but not much else.
Once you publish your cart with the exports/ folder to the BBS, other people using yotta will be able to use it in their projects with yotta add #your_bbs_cart_id
followed by a yotta apply
. I propose a convention of providing a primary 'include entry point' (if applicable) of 'main.lua' - so placing your library file in your /ram/cart/exports/main.lua
. But, all files in your exports/ folder will end up in the end-user's lib/your_package_name/ directory, so you can do as you will.
Building packages for use with yotta
It's also simple! Make an exports folder in your cartridge (at /ram/cart/exports
). Assume the contents of your cartridge's exports directory will be overlaid atop the end-user's Picotron drive starting at the root level. So, if you'd like to package a system-wide terminal utility, you would want to ensure that /ram/cart/exports/appdata/system/util
exists as a folder, and inside of that, you would place your utility (like new.lua
!).
When end users use yotta to install your package cartridge, it will copy the exports tree over the root filesystem, and when users instruct yotta to uninstall it, it will remove the files present in your export tree from the user's filesystem (and will clean up empty directories if it leaves them).
If you don't want to require your end users to use yotta to install your package, and your cart does nothing else but hold the package, you could use my package installer (same as my library container). It will let people either manually copy the files out of /ram/cart/exports
or will offer to install/uninstall it to their with similar logic to yotta (but without requiring yotta to be installed) by pressing X while running it.
What if a BBS cartridge updates? What if I don't want that? What if I do?
If you include a BBS cartridge, you can specify a revision just like you could with the load
command... or you can omit it to get the latest. You can choose at yotta add
time. For instance, if you wanted to fetch the first release of my utility shim cart, you'd use yotta add #lib_utilinst-0
. When you used yotta apply
or yotta force
, it would always grab that version. If I fixed a bug in it and updated it, though, its cart ID would change to #lib_utilinst-1
, but the first revision would remain accessible and would be fetched by yotta in this case. If you wanted yotta to automatically grab the latest revision possible, you can yotta add #lib_utilinst
- and whenever you run a yotta apply
or yotta force
, it would grab the latest revision (#lib_utilinst-1
or further).
Changelog:
- r3: added yotta_manual.txt for viewing in the info viewer by @ksting
- r4: added /appdata/system/man/yotta.1 for viewing in the 'man'-style manual viewer by @jesstelford
- r5: yotta v1.1: - now actually uploaded! smh
- smarter package-mode file overwriting & uninstallation:
- uses CRC32 to determine if a file it's about to overwrite is an old or current version that can be upgraded/replaced, or if it's another file not owned by yotta.
- by default for installations or upgrades, it will make a backup of the unknown file (file.txt -> file.txt.bak) and will install its packaged files as instructed.
- using the -g flag will make it gentle, and it will simply skip the file instead of backing-up and installing. it will install the other files that don't have a conflict.
- using the -f flag will make it forceful, and it will simply overwrite the file instead of backing-up.
- for uninstallations, it will only remove files that match checksums that it believes it owns, and will thus leave modified or non-matching files in-place.
- CRC32 support in packages is optional. See my crc32 utility for more information - you can just run
crc32 -V exports
from the root of the cartridge you intend to distribute, every time you're about to make a release, and it will understand. - added
yotta util update
: will download or copy a new version of a system package and install it over the old one. this works for yotta itself, too, so in the future you can update yotta this way without disruption. - fixed
yotta apply
bugs: it wasn't cleaning up right when packages were removed withyotta remove
. now it does! - fixed yotta adding multiple instances of the same dependency or package. it won't do that anymore.
- moved global yottafile into /appdata/yotta instead of /appdata/system to keep everything tidy.
- allow specifying a package or dependency for uninstallation or update by its 'short name' listed alongside it in
yotta list
oryotta util list
(eg,my_pkg
can be used instead of/carts/wip/my_pkg.p64.png
)
In a way, this package cartridge containing yotta is also an example for how to use it at a basic level. If you load #yotta
and cd to /ram/cart
, you should be able to inspect both its lib/
and exports/
directories.
If you open lib/yottafile.pod
, you'll be able to see the internals of the yottafile I used to bring in the BBS dependency from my package installer - the deps key contains #lib_utilinst-0
as a desired dependency, and it's tracking the single dependency's file and a folder under tracked._bbs_lib_utilinst_0 (the dependency folder and its singular main.lua within). In the tracked._refs key, it notes that despite what's currently desired (which is the deps key), #lib_utilinst-0
is now currently installed. You should never have to edit these files directly, yotta will do it for you, but you can do whatever you want!
This dependency is then included in my cart's main.lua to be used: include "./lib/_bbs_lib_utilinst_0/main.lua"
Meanwhile, in the cart's exports/ folder, you'll see a filesystem intended to be overlaid atop your Picotron's root filesystem. A single file is to be installed at a specific location, so within exports/ it lies at its intended location to be merged in by the installer: exports/appdata/system/util/yotta.lua
. If you were to press X while the cart is running and yotta is uninstalled, it would place yotta.lua into your /appdata/system/util/ directory. If you pressed it again, it would remove yotta.lua from your util directory. The mechanisms by which the cart installs and uninstalls yotta are very similar to how yotta itself would install or uninstall system packages for you via yotta util
.
A package is intended to be installed to the Picotron drive as permanent software, like a new tool in /appdata/system/util/ or a new wallpaper in /appdata/system/wallpapers/. Yotta will install them in the right place, and will allow for cleanly uninstalling them later, too. In this way, yotta functions like apt in Ubuntu or pacman in Arch Linux.
A library is intended to have content that is consumed by another cartridge. Examples might be a code library that does 3D math, or a collection of reusable sprites intended to be used across multiple projects. It can be created once, distributed in cartridge form and even updated in-place on the BBS or in a personal library, and yotta will manage importing those resources into future projects. In this way, yotta functions like npm for javascript/typescript, composer for php, or pip for python.
Since both involve taking cartridges and extracting exported data for installation and use somewhere else (either in a package's library directory, or to the system), I combined these into one utility.
I'm having a head spin trying to figure out how to set up my lib. Do you have an example cart of how i should setup the liberay container cart?
Loving yotta!
I've just released a man
util which uses it for installation - works super well! 🎉
Would you consider adding a man page to yotta too?
It would live at /appdata/system/man/yotta.1
, and should have a similar format to the docs for man (p8scii is supported!), then anyone with both yotta
and man
installed can get to the docs with a simple man yotta
.
@Hessery sorry I didn't get back to you in time - it looks like you figured this out, I saw winStay, which is a great idea!
But I figure for others who are seeking an example of a yotta library cartridge, I'll add that the library this yotta cartridge uses to provide the runnable installer/uninstaller interface can be found here: https://www.lexaloffle.com/bbs/?tid=140829 with BBS ID #lib_utilinst
That lib_utilinst cartridge has a single library file intended to be imported into other cartridges (like this yotta one!) placed into its exports/ folder. And.. that's it! That cartridge's main entry point also happens to include that exported library file to use it to display something, too, but the entry point part of the code doesn't get exported via yotta.
@jesstelford I will definitely do this! I've already included a manual file for ksting's 'info' command already, but until the community settles on a preference, I will totally duplicate work to have universally accessible documentation :)
Oh, I didn't know about ksting's info command! Love that us great minds are all thinking alike 🎉
The new man page looks good.
Is the source for yotta hosted anywhere (eg; on GitHub)? Would be good to submit some PRs 👍
@jesstelford no current external source-code hosting or tooling. i'm a developer by profession, and my favorite thing about pico-8 and picotron is that it's a little insulated from all that while still being fun to work and tinker on, so i'm reticent to invite in big external software development tooling and services to this cozy little corner and turn it into the same experience as my work!
i do think i'll be writing a multi-file patch utility and maybe a basic version control system to help manage my projects and have a way for folks to submit patches to any carts on the BBS here, linux mailing list diff style, but it's just imaginary for now. i'll happily consider old-fashioned style fix suggestions here though, in code blocks :)
Yotta v1.1 has been released.
If you've already got yotta installed, you can execute yotta util install #yotta
to have yotta install its new version over itself. Then, when you do a yotta version
, it should tell you it's v1.1 and also conveniently perform some minor migrations:
- move global yottafile from /appdata/system to /appdata/yotta
- clean up new CRC checksumming files the new yotta package came with that the old yotta would have dutifully installed, not knowing they were special
Any command will trigger this migration if it hasn't happened yet, but yotta version also confirms you got the upgrade.
I've tested installing this as an upgrade as above, and as a fresh package with no yotta installed, and it all seems to work as expected- old and new functionality alike.
In the future, you can install newer yotta versions with yotta util update #yotta
.
This version tries a bit harder to not clobber or uninstall files it doesn't think it owns. It uses code common to my new CRC32 utility to help it do this. You can control its behavior a bit - if you want it to skip over existing files outright, you can ask it to be gentle like: yotta util install -g #man
. If you don't care about what's there, you can ask it to be forceful like: yotta util install -f #man
. By default, it will make a backup of a conflicted file and install its own (it will 'cp file.txt file.txt.bak`, basically)
If you encounter any bugs or issues, please let me know and I'll happily address them :)
the 5th revision of yotta is not present on bbs, so I can't upgrade it to 1.1
@snakebyte ouch, dangit - thank you for letting me know. i must have failed to edit the -4 to -5 in the main post when i wrote the release notes :( this has now been corrected. my apologies.
Hey, I'm trying to install this, but anytime I try, it just changes briefly to installed, then immediately back to uninstalled. Am I doing something wrong?
@Transference was having this problem too but figured it out
open up the file lib/utility_stub/main.lua
in the cart
on lines 43 and 59, when its detecting the key press, remove the or btnp(5)
and or btnp(4)
there seems to be a picotron bug right now where although the keyp and btnp calls refer to the same key, they're true on different frames, resulting in a double input.
Is there a way to search yotta or list all installable packages with yotta?
[Please log in to post a comment]