App-rs
view release on metacpan or search on metacpan
rs adopt
=head1 DESCRIPTION
(Please see the section L</CPAN> and
L<my TPF proposal|https://github.com/057a3dd61f99517a3afea0051a49cb27994f94d/rslinux/blob/rs/TPF-proposal.pod>
for my ongoing effort to marry C<App::rs> and CPAN.)
RSLinux was born out of desire for freedom. Back in 2012, I was using
ArchLinux, as with many distributions at that time, it's switching to
systemd, and I would be forced to switch to it if I chose to update. It
frustrated me deeply, as I always seek freedom, from a very young age, and I
knew from my own experience that no matter how wonderful a thing is, it
will become a demon that haunts me once I'm being forced to do it. I made
up my mind to create something of my own so that I have complete freedom
to choose how it would be.
At first, I got my hand dirty with LFS, succeeded and got pretty satisfied
with it. Later in 2013, I made it again without following the LFS book, I
tried a different bootstrapping process with what I thought was right and
necessary, and it fits my mind much better. I typically rebuild my system
on an annual basis, after I did it in 2014 I gradually realized its problem,
without a package manager, thus an easy way to remove installed package,
I tended to dislike denpendency, and prefer a minimalist system, which
prevented me to explore since I knew I would have no easy way to clean up the mess
after I installed a lot of things, experimented with them a bit, and then
decided that I don't want them anymore.
I knew it was bad, and something to be dealt with. In the end of 2015, I
was working on something that's recursive, and it inspired me to
write a simple and elegant package manager B<rs>, since directory and files,
which a package manager deals everyday, recursiveness is in their nature.
B<rs> keeps a database of the metadata of every file/directory that you didn't ask
it to ignore, you will typically ask it to ignore something like C</tmp>,
C</proc>, etc., if you're using it to manage system wide packages. With
B<rs> you compile and install a package from source as usual, and when the
installation process is done, you run C<rs diff oid>, B<rs> then starts
a scan of the root directory into which you just installed your package,
and during the scan process, it compares what's actually there with the
database, calculate the difference between them as well as updating the
database, and when the scan process ends, the difference is then tagged
as C<oid> in the database, serialized and stored as C<oid.rs>, and the
database is saved as well.
This serialized difference is what B<rs> considers as a package, and it could
be transferred across machines and installed using C<rs patch>, it's very
much like a tarball, but I could not just use a tarball since I need to maintain
all these metadata in the database when patching, instead of parsing a tarball
I thought I might just use a trivial binary format that integrates well with
B<rs> and suits my need.
Being someone who came from LFS, I knew this is a game changer, it gave me a
complete new experience, besides the ability to explore without any hesitation,
I could easily upgrade, or switch between multiple versions of package;
I could now compile once on desktop, and then install the compiled package
on laptop, or vps; I could select a few packages, patch them, and then make
a bootable usb disk or cdrom, or a complete environment that's suitable to
put into a container and run web service. I sincerely believe anyone who
likes LFS will like it, and anyone who likes the freedom of LFS but hated
the inconvenience will like it also, since B<rs> eliminates ninety percent
of the inconvenience yet without sacrificing even a tiny bit of the freedom.
RSLinux is a Linux distribution, but not necessarily so, it's a way of doing
things more. You do not need to take a full commitment using it as a
distribution, there're almost always packages that you care about more and
want to follow closely, while other people haven't packaged it for you,
B<rs> is a perfect choice for this, you could use B<rs> to properly manage
packages somewhere inside your home directory while still using your
favorite distribution.
Till this day, I still haven't tried systemd once, I don't know one single
objective reason why I don't use it, but it's true enough that it's the
very first motivation that got all these things started. I guess that's just
how the world is, few things are objective while basically everything is
subjective. Nevertheless, the goal of B<rs> is to avoid all these subjective
feelings and views on how a distribution should be made, which init system
should be used, what configure switches, compiling flags should be passed,
whether stable version should be preferred over bleeding edge version or the
other way around, how a filesystem hierarchy should be laid out. Whatever
you feel is right, you just go for it, and what B<rs> does is to make this
process easier. Since the packaging by C<diff> method is general, it works
with every single package with no exception, you don't need any tweak for
an individual package, thus most packages need zero configuration, and all
the build instructions I used to build a distribution that I use everyday
are only literally one hundred lines long.
Still, RSLinux will never be easier than a classic distribution where other
people do everything for you, but there're still many things to do and
improve, and I do think in the long run the effort will be negligible
and the reword will be immense. If you never tried LFS or something like
it before, I suggest you use B<rs> to manage a couple of packages user wide
while retain your distribution untouched, once you get your way around it,
then maybe consider to jump on the ship, there's nothing to be afraid of.
=head1 OPTIONS
=over 4
=item * --root=<dir>
Specify the directory in which B<rs> will operate, it will scan this
directory for newly installed files during a C<diff> operation, and
will put or remove files under it during a C<patch>, C<remove> operation
respectively.
=item * --db=<file>
Specify the database where all the metadata of the files and directories
in C<root> is stored. If it doesn't exist yet B<rs> will create an empty
one for you. But you should always specifiy it since it's used by
all of the commands.
=item * --pool=<dir>
The direcory where a generated package will be stored during a C<diff>
command. It's also occasionally used when you C<remove> a package, see
the L</remove> command for more detail.
=item * --prefix=<dir>
You can choose anything you want as C<oid>, usually you want to use
something meaningful like the package name with the package version appended,
such as C<gcc-6.4.0>.
If the C<oid.rs> already exists in C<pool>, the new difference will be merged with
the old, this way the C<diff> command could do limited amending, that's most
useful when you forgot to install something, like documentation, you could
always install it later and merge with the content you installed previously.
See L</AMEND> for why amending using C<diff> is limited and how to do
arbitrary amending.
If the option C<dry> is given, the difference will only be displayed, that's
handy to check if your system is consistent with what's recorded in the database,
the difference should be empty if you didn't do a mannual installation, or you
can have a preview of what's installed if you did do that.
=item compile
The C<compile> command integrates the C<diff> and C<tag> commands to make
it easier for you to install a package from source, it automatically
compiles and installs a package, then does a C<diff> command followed
by a C<tag> command.
The compiling instructions are taken from the L</build> configuration file
with the entry associated with the package name. The package name could
be set explicitly by the C<--package> option, or more commonly it's derived
from C<oid> by using the longest prefix of it before the C<-> character,
for example, with C<man-pages-4.15> as oid the package name will default to
C<man-pages>, and with C<perl-v5.22.3> it will be C<perl>.
There're three types of compile commands, compile from a tarball, a git directory,
or a prepared source tree.
=over 4
=item * compile <tarball>
B<rs> will extract, compile, then install the tarball in the direcory
C<compile-in>, or the current directory if it's not specified.
The filename of the tarball, with the extension name like C<.tar.gz>,
C<.tar.xz>, etc. stripped, is used as C<oid> to the C<diff> command. For
example, if the tarball is C<man-pages-4.15.tar.xz>, the C<oid> will be
derived as C<man-pages-4.15>, just C<mv> the tarball if you want to change
the C<oid> to something different.
=item * [--branch=<branch>] compile <git-directory> <oid>
B<rs> will do a C<git clone> from the specified git directory, checkout branch
or tag specified by the C<--branch> option or C<oid> if absent, in C<compile-in>,
and then compile and install the package.
=item * --prepared compile <source-directory> <oid>
B<rs> will C<chdir> into the prepared source directory and start the compiling
process, thus the C<compile-in> directory is ignored in this case. It's
useful when you need more complex preparations of the source like applying some
patches, or initializing git submodules, etc.
=back
The C<compile> command really covers ninety percent of the case, but it may
not be flexible enough to compile every package in the wild, but that's
actually okay, since you could always do a manual installation followed
by a C<diff> command.
=item patch
C<patch> takes one argument, a compiled package file <path/to/oid.rs>, which
is produced by a previous C<diff> command, it then installs the package into
C<root> and tag it as C<oid>.
Optionally, one or more C<--subtree> could be provided so that only part of
the package is installed, for example, C<--subtree=bin/> will instruct B<rs>
to only install anything under the C<bin> directory of the package. It's
also particularly handy to let a file be from a specific package, if there're
multiple packages that contain it.
=item remove
C<remove> takes one argument, the C<oid> of the package to be removed.
B<rs> will remove both the content of the package under C<root> and
its metadata in the database.
Sometimes, different packages install files into the same location. B<rs>
takes care of that by recording a list of owners associated with a file,
along with the timestamps when ther're installed, that's why you are seeing
all the C<oid>s floating around the manual, it means I<owner's id>. And
when you remove a package, a file is removed if and only if this package
is the most recent owner of it, and if it's not, nothing will happen,
only the entry in the owner recording list will be removed. On the other hand, if
you're removing a package that's indeed the most recent owner of a file,
but this file has multiple owners, then the file will be restored
to the version of the second most recent owner. That's why I said earlier
that the C<--pool> option is used not only when diffing, but also removing
sometimes. Suppose the second most recent owner is C<oid>, then B<rs> will
try to parse the compiled package C<oid.rs> in C<pool>, and restore the file
according to it.
=item tag
C<tag> takes one argument C<oid> and displays a list of files which are
owned by it, followed by the detailed metadata about them in the database
as JSON.
=item which
Takes an absolute path or a path that's relative to the C<root>, display
its entry in the database, useful to find out to which package a file belongs.
=item list
Print a full list of installed packages, sorted from the most recent to the least.
=item crowded
Find out the crowded places, where more than one package likes to reside, that's
useful if you want a file from a specific package, and also to discover
accidental overwrite.
=back
( run in 2.156 seconds using v1.01-cache-2.11-cpan-98e64b0badf )