Note

The Funtoo Linux project has transitioned to "Hobby Mode" and this wiki is now read-only.

Difference between revisions of "Funtoo:Metatools/Advanced Usage"

From Funtoo
Jump to navigation Jump to search
 
(95 intermediate revisions by 6 users not shown)
Line 1: Line 1:
This page documents how to set up a local development environment that will allow full local testing of any of your customizations, bug fixes or improvements to Funtoo Linux. This includes generating your own meta-repo and kits with your custom changes, as well as getting metro set up for unit tests. We recommend that all Funtoo Linux developers who will be submitting ebuild improvements to use set up this environment for local testing of changes. This setup also allows more involved changes to be tested and validated locally, so that your contributions to Funtoo are as production-ready as possible.
{{Subpages|Gitolite Setup}}
 
{{Important|These pages are out of date. Please see the latest [[Funtoo:Metatools]] page for usage information.}}


== Overview ==
== Overview ==


For our local development setup, we will be using [http://gitolite.com gitolite]. Gitolite will make things quite a bit easier by managing git repositories for us. ''Think of gitolite as your own private GitHub that has no Web user interface'' (we modify its settings by pushing to its special {{c|gitolite-admin}} repo) and you'll have a pretty good idea of what gitolite does. We will be using the following systems in these examples:
Funtoo Linux uses "merge scripts" to create its kits and update meta-repo. These scripts work by sourcing ebuilds from various overlays, and combining them using special algorithms to yield the kits you use. A meta-repo is also generated, which points to the specific kits generated that are designed to work together.


* {{c|repohost}} - this system will be running gitolite under the {{c|repos}} user account and will house git repositories for meta-repo and kits so that they are stored at a handy central location.
Before starting, please read and understand the following pages:
* {{c|ryzen}} - in these examples, this will be the primary development workstation, which will be used for editing cloned git code as well as generating custom kits. Once generated, the custom meta-repo and kits are pushed up to {{c|repohost}}.
* [[Kit-fixups]]
* [[Kit-fixups/FAQ]]


{{Note|When you follow this guide, it is certainly possible to have {{c|repohost}} and {{c|ryzen}} be the same computer.}}
== Different Approaches ==


{{Important|This document assumes you have basic knowledge of {{c|ssh-keygen}} and how to generate public/private SSH key pairs. If you don't know how to to this, see [[Funtoo Containers#Generating SSH Keys|Generating SSH Keys]] for quick steps or [[OpenSSH Key Management, Part 1]] for a more detailed introduction. For this article, you'll probably want to generate a private keys without a passphrase, which is more convenient but a much greater security risk if the private key gets compromised, or one with a passphrase but using [[keychain]] to manage ssh-agent for you.}}
{{c|merge-all-kits}} can be used in a variety of ways. If you are an individual developer, you may want to use {{c|merge-all-kits}} in ''developer mode'', which is its default mode. Developer mode makes it easy to generate a meta-repo and kits that you can test locally.


== Gitolite  ==
In developer mode, a {{c|meta-repo}} and all automatically-generated kit git repositories are created from scratch. These git repositories will have no remotes, so they will simply exist locally on disk, and they will not have any history shared with the Funtoo project. It you look at the commit history for the kits and meta-repo, you will see that they essentially have no history.


=== Installation ===
Another way to use {{c|merge-all-kits}} is with {{c|gitolite}} as a remote, which is documented under the [[#Gitolite Setup|Gitolite Setup]] sub-page. Using this configuration, {{c|merge-all-kits}} will write all of its destination git repositories to gitolite. You can then configure other systems to {{c|ego sync}} from gitolite as a source. This can be good in a distributed development environment. This method can also be used to create a meta-repo and kits that ''diverge'' from Funtoo's kit but still connect to its history.


To set up gitolite on your LAN, first choose a system that will be used to house your meta-repo and kits git repositories. You can do this on the same system you will be using for testing (and even development), or you can set it up on a dedicated system. It's actually fine to set this up anywhere on the Internet, as git will use ssh to access this repository, but for the purposes of this article, we're assuming you're setting it up somewhere on your LAN.  We will refer to this system as '''repohost'''.  
Finally, the {{c|merge-all-kits}} script can be run in a production mode, which is very similar to using it with gitolite except that you may be pushing up your destination meta-repo and kits to a public location like GitHub or GitLab.


On this system, perform the following steps as root:
When first starting out with {{c|merge-all-kits}}, you should definitely start with developer mode and see if that meets your needs first.


{{console|body=
== Getting The Code ==
# ##i##useradd -m repos
}}


The {{c|repos}} user will be a dedicated user account on the system that will have gitolite enabled and will house our git repositories. Now, we are going to {{c|su}} to this new user on '''repohost''' and perform gitolite configuration:
You can find the code that does this on code.funtoo.org, housed at [https://code.funtoo.org/bitbucket/projects/CORE/repos/merge-scripts/browse code.funtoo.org]. The script that does all the heavy-lifting is called {{c|merge-all-kits}}. Let's clone it from git, on the machine that will be generating new kits and meta-repo:


{{console|body=
{{console|body=
# ##i##su repos
$ ##i##git clone https://code.funtoo.org/bitbucket/scm/core/merge-scripts.git
$ ##i##git clone https://github.com/sitaramc/gitolite
$ ##i##install -d ~/bin
}}
 
Now, as the {{c|repos}} user, add the following to the end of your {{c|~/.bashrc}} file:
 
{{file|name=~/.bashrc|body=
export PATH=$HOME/bin:$PATH
}}
}}


What we're doing is setting up a {{c|bin}} directory where the {{c|gitolite}} command will be installed, which will be in your path, so that you can use it more easily. With this done, perform the following steps:
You will also want to install the following dependencies so that the code can run:


{{console|body=
{{console|body=
$ ##i##source ~/.bashrc
# ##i##emerge jinja lxml
$ ##i##gitolite/install -ln
}}
}}


Now, your {{c|repos}} account is almost ready to be used for hosting repositories. The way gitolite works is that it is going to basically take over ssh access to the account, so that when you connect via ssh with git, it will perform its own authentication. For this to work, you will need to enable your own "master key" to access gitolite. To do this, you'll want to decide from which account you'll want to administer gitolite itself. I prefer to use my "drobbins" account on my development workstation '''ryzen''', so I will copy my ssh public key from {{c|~/.ssh/id_rsa.pub}} to {{c|/var/tmp/ryzen-drobbins.pub}} on the gitolite system, and then perform the following steps to "prime" gitolite with this admin public key:
== Configuration and Paths ==


{{console|body=
In general, you should run {{c|merge-all-kits}} as a regular user, and this user needs to be a member of the {{c|portage}} group.
$ ##i##gitolite setup -pk /var/tmp/ryzen-drobbins.pub
}}


Gitolite will now be initialized to recognize the {{c|drobbins}} remote account as an administrator, which will allow this remote account to clone from {{c|repos@repohost:gitolite-admin}} and push any changes to this special git repository which contains the master configuration for gitolite. This is important because we will be performing the rest of gitolite setup over ssh, using this account.
In the user's home directory, create a {{f|~/.merge}} directory with the following contents:
 
{{Note|OK, gitolite is installed on '''repohost'''! From this point forward, we will be using the {{c|drobbins}} (or equivalent) account on your development workstation to configure gitolite remotely.}}
 
=== gitolite-admin Clone ===
 
Now that gitolite is ready on '''repohost''', we can do everything else remotely. I am going to use the {{c|drobbins}} account on my development workstation '''ryzen''', and you will use whatever account is associated with the public key you loaded into gitolite. I like storing my development repos in {{c|/var/src}} on '''ryzen''', so I'll go ahead and clone the gitolite-admin repo to that location so it can live along all my other git repos. Feel free to put this git repo wherever you like to store git repos that you develop on:
 
{{console|body=
$ ##i##cd /var/src
$ ##i##git clone repos@repohost:gitolite-admin
$ ##i##cd gitolite-admin
}}
 
We are now ready to configure gitolite. We'll do this by modifying {{c|conf/gitolite.conf}} in the git repo and adding new ssh public keys to {{c|keydir/}} as needed. You will see that the initial public key you used to "prime" gitolite already exists in {{c|keydir/}}. Once we change the configuration, and potentially add new public ssh keys that we want to grant access to gitolite-managed repositories, we'll perform a {{c|git commit}} and {{c|git push}}, and if gitolite doesn't complain about our changes, they'll take effect immediately. We'll go through our initial configuration steps below.
 
=== gitolite Configuration ===
 
Since I will be generating meta-repo and kits on '''ryzen''', this system will need to have permissions to create repositories in gitolite. I would typically do this on '''ryzen''' as follows. First, as root:
 
{{console|body=
# ##i##cp /root/.ssh/id_rsa.pub /var/tmp
}}
 
Then, as my regular {{c|drobbins}} user that I typically use to perform development:
 
{{console|body=
$ ##i##cd /var/src/gitolite-admin
$ ##i##cp /var/tmp/id_rsa.pub keydir/ryzen-root.pub
$ ##i##git add keydir/*
}}
 
{{Note|It's important to change the filename of the public keys you are adding to the {{c|gitolite-admin}} repository. I typically use the format {{c|host-user.pub}}.}}
 
Now, we're ready to edit {{c|conf/gitolite.conf}} so that it looks like this:
 
{{file|name=gitolite.conf|body=
# Group definitions below, starting with @. This makes it easy to associate multiple ssh keys with a particular person.
 
@drobbins = ryzen-drobbins
@repomgr = ryzen-root
 
# To enable read-only access to your meta-repo and kits, use this along with
# commented-out line under wildrepo. You will need to add box1-root.pub and
# box2-root.pub to keydir/ as well. This is good for boxes that will be testing
# your meta-repo and kits only but should not be able to modify them.
 
#@reporead = box1-root box2-root
 
# repositories:
 
# SPECIAL ADMIN REPO BELOW -- modify with care! I've switched over to using the @drobbins group instead of
# referencing the individual ryzen-drobbins key directly.
 
repo gitolite-admin
    RW+    =  @drobbins
 
# AUTO-CREATED (wild) REPOS: gitolite will auto-create repos under wildrepo/ for us
# upon initial clone of any path within, if the repo doesn't already exist.
 
repo wildrepo/..*
    C      =  @repomgr
    RW+    =  @repomgr @drobbins
# NOTE: to enable read-only access for certain boxes, uncomment this line:
#  R      =  @reporead
}}
 
== merge-scripts ==
 
=== Overview ===
 
Funtoo Linux uses "merge scripts" to create its kits. These scripts work by sourcing ebuilds from various overlays, and combining them using special algorithms to yield the kits you use. A meta-repo is also generated, which points to the specific kits generated that are designed to work together.
 
Required for merge scripts is  {{c|dev-python/lxml}}.
 
=== The Code ===
 
You can find the code that does this on GitHub, housed at https://github.com/funtoo/merge-scripts. The script that does all the heavy-lifting is called {{c|merge-all-kits.py}}. Let's clone it from git, on the machine that will be generating new kits and meta-repo. In our example, this will be as the root user on ryzen:
 
{{console|body=
# ##i##cd /root
# ##i##git clone https://github.com/funtoo/merge-scripts
}}
 
{{Note|While it is possible to use your own custom merge script repository, we recommend starting by using our official merge-scripts repository on GitHub, and progress to using your own fork of merge-scripts only when you need to.}}
 
=== Configuration ===
 
Now that merge-scripts is cloned, we will need to create a {{c|/root/.merge}} configuration file. Use the following file as a starting point:


{{file|name=/root/.merge|body=
{{file|name=/root/.merge|body=
[sources]
[sources]


flora = https://github.com/funtoo/flora
flora = https://code.funtoo.org/bitbucket/scm/co/flora.git
kit-fixups = https://github.com/mygithub_user/kit-fixups
kit-fixups = https://code.funtoo.org/bitbucket/scm/co/flora.git
gentoo-staging = https://github.com/funtoo/gentoo-staging
gentoo-staging = https://code.funtoo.org/bitbucket/scm/auto/gentoo-staging.git
 
[destinations]
 
base_url = repos@repohost:wildrepo/staging


[branches]
[branches]
Line 157: Line 55:
kit-fixups = master
kit-fixups = master
meta-repo = master
meta-repo = master
[work]
source = /var/git/source-trees
destination = /var/git/dest-trees
}}
}}


==== Sources Section ====
By default, {{c|merge-all-kits}} will create a {{c|~/repo_tmp}} directory where it will store all of its work. Inside {{f|~/repo_tmp/source-trees}}, source git trees that will be used to generate meta-repo will be cloned. Inside {{f|~/repo_tmp/dest-trees}}, git repositories will be created to write results into. The meta-repo will be stored at {{c|/~repo_temp/dest-trees/meta-repo}}, and in developer mode, the kits will be stored in meta-repo, at {{c|~/repo_tmp/dest-trees/meta-repo/kits}}, so that meta-repo is configured 'ready to use' at it would appear at {{f|/var/git/meta-repo}}. When 'production' mode is specified via the {{c|--prod}} switch, the meta-repo will not have kits stacked inside it but instead the kits will be written directly into {{c|~/repo_tmp/dest-trees}}.
 
Let's walk through this configuration file. The {{c|[sources]}} section defines locations of repositories that the merge scripts will use as sources for creating kits and meta-repo. In the above sample config, we are using the official [[Flora]] repository from Funtoo, and the official gentoo-staging repository used by Funtoo, but we are using our own fork of https://github.com/funtoo/kit-fixups, which will allow us to add new ebuilds that will appear in kits, such as bug fixes to existing ebuilds in kits, as well as security fixes. For a core Funtoo Linux developer, this is a good way to start. If you are more interested in contributing third-party ebuilds, then you may instead choose to create your own fork of https://github.com/funtoo/flora, and use our standard kit-fixups repository. Or, you could choose to create forks of both. The recommended best practice is to use our upstream repos when possible, and fork only those repos you want to customize. This way, you'll ensure that you have the most up-to-date versions of ebuilds in those unforked repos.
 
==== Branches Section ====
 
The {{c|[branches]}} section is used to define the default branches that are used by the merge-scripts. In general, sticking with {{c|master}} is fine, but if you need the flexibility, you can point the merge scripts to a particular feature branch to use instead, for example.
 
==== Work Section ====
 
The {{c|[work]}} section is used to define paths where the merge-scripts will do their work. The {{c|source}} and {{c|destination}} settings above are good defaults, and define where the merge-scripts will clone source repositories and destination (written to) repositories, such as kits and meta-repo. These are kept in two separate hierarchies so they don't get mixed up.
 
== Generating New Kits ==


With this all configured, you are ready to generate new kits. These kits will be generated as root on your development system, and will be stored on '''repohost'''. Here are the steps you'd perform:
A metadata cache will also be created and stored at {{c|~/repo_tmp/metadata-cache}}, and your user must be a member of the {{c|portage}} group for {{c|merge-all-scripts}} to be able to properly generate the metadata cache.


{{console|body=
== Running Merge-All-Kits ==
# ##i##cd /root/merge-scripts
# ##i##bin/merge-all-kits push
}}


Before starting the script for the first time you should configure your git user.name and user.email variables.
To run {{c|merge-all-kits}}, use it as follows:


{{console|body=
{{console|body=
# ##i##git config --global user.email "you@example.com"
$ ##i##path/to/merge-scripts/bin/merge-all-kits 1.4-release
# ##i##git config --global user.name "Your Name"
}}
}}


{{c|merge-all-kits}} will proceed to create new kits and meta-repo, and will push them up to repos@repohost:wildrepo/staging/meta-repo, repos@repohost:wildrepo/staging/core-kit, etc. This process can take quite a while but has been optimized to run quickly on multi-core systems.
The script will then run, and it will git clone flora, kit-fixups and gentoo-staging from the URIs in the {{c|~/.merge}} file, and assemble them into a complete meta-repo. The meta-repo will be located at {{f|$HOME/repo_tmp/dest-trees/meta-repo}}.
 
== Using New Kits ==


Now that the new meta-repo and kits are created, here's how you'll use them on an existing Funtoo system, instead of your official Funtoo meta-repo and kits. First, we'll want to modify {{c|/etc/ego.conf}} as follows:
To use the {{c|meta-repo}} for testing, you can add the following lines to {{f|/etc/ego.conf}}:


{{file|name=/etc/ego.conf|body=
{{file|name=/etc/ego.conf|body=
[global]
[global]
 
meta_repo_path = /home/user/repo_tmp/dest-trees/meta-repo
sync_user = root
sync_base_url = repos@repohost:wildrepo/staging/{repo}
 
# Yes, you are supposed to have a literal "{repo}", above. Ego recognizes this special pattern.
 
# You can have whatever [kits] section you want, below...
}}
}}


You will want to make sure that whatever system is connecting to '''repohost''' is permitted by gitolite, and has its {{c|/root/.ssh/id_rsa.pub file}} stored and committed to the gitolite-admin repository's {{c|keydir/}} and is referenced in {{c|conf/gitolite.conf}}. Otherwise, gitolite will not allow this system to connect. Of course, if you are configuring this on the system that's running {{c|merge-all-kits.py}}, it already has RW permissions to these repositories. Otherwise, you will want to make sure that gitolite has the system's keys as part of its {{c|@reporead}} group.
Then, using ego 2.8.0 or later, run the following command:
 
{{Note|We change the {{c|sync_user}} to {{c|root}} to force {{c|ego sync}} to use {{c|/root/.ssh/id_rsa}} for authentication. By default, {{c|ego sync}} will attempt to use the {{c|portage}} user which does not have a private key installed, and thus will not be able to authenticate with gitolite. Rather than mess with the {{c|portage}} user and give it a proper home directory and ssh key pair, it's easier just to not drop perms to {{c|portage}} in the first place.}}
 
Now, let's move the current meta-repo out of the way -- you can also simply delete the existing meta-repo. And then we'll re-run {{c|ego sync}}:


{{console|body=
{{console|body=
# ##i##cd /var/git
# ##i##ego sync --in-place
# ##i##mv meta-repo meta-repo.official
# ##i##ego sync
}}
}}


Ego will now sync your custom repository. If you type {{c|emerge -auDN @world}}, ego will now be using your custom kits, rather than the official Funtoo ones. This means that you can perform a variety of things you couldn't before. You can now add your own custom ebuilds to your fork of {{c|kit-fixups}}, and {{c|merge-all-kits.py}} will automatically incorporate these changes into your own custom kits. This will allow you to locally test any changes before submitting them as pull requests to Funtoo. You will also be able to maintain your own meta-repo and kits with your own local modifications, and have your systems use these meta-repo/kits instead of the official Funtoo ones.
This will ensure that the proper kit branches in your meta-repo are checked out and that all the repos.conf and profiles files in {{c|/etc/portage}} are configured correctly for your repository to be used. Note that no actual "{{c|git pull}}" will be performed -- this is intentional and a special feature of the {{c|--in-place}} option -- because your local git repositories have no remotes to pull from and contain all the information they need to be used.


== Changing Repo Definitions ==
You're now ready to use your meta-repo directly:


Now that you have generated your first meta-repo, let's look at the key file that defines what overlays and repositories are used to create meta-repo, as well as what kit branches exist, and which ones are prime and which are not. You will want to turn your attention to the {{f|kit-fixups/modules/fixups/foundations.py}} file, which [https://github.com/funtoo/kit-fixups/blob/master/modules/fixups/foundations.py can be viewed here on GitHub]]. Let's take a look at various sections of this file:
{{console|body=
 
# ##i##emerge foo
{{file|name=foundations.py|lang=python|desc=Top of foundations.py file|body=
#!/usr/bin/python3
 
from enum import Enum
 
 
class KitStabilityRating(Enum):
PRIME = 0  # Kit is enterprise-quality
NEAR_PRIME = 1  # Kit is approaching enterprise-quality
BETA = 2  # Kit is in beta
ALPHA = 3  # Kit is in alpha
DEV = 4  # Kit is newly created and in active development
CURRENT = 10  # Kit follows Gentoo currrent
DEPRECATED = 11  # Kit is deprecated/retired
 
 
def KitRatingString(kit_enum):
if kit_enum is KitStabilityRating.PRIME:
return "prime"
elif kit_enum is KitStabilityRating.NEAR_PRIME:
return "near-prime"
elif kit_enum is KitStabilityRating.BETA:
return "beta"
elif kit_enum is KitStabilityRating.ALPHA:
return "alpha"
elif kit_enum is KitStabilityRating.DEV:
return "dev"
elif kit_enum is KitStabilityRating.CURRENT:
return "current"
elif kit_enum is KitStabilityRating.DEPRECATED:
return "deprecated"
}}
 
At the top of the file, we define an [[Wikipedia:Enumeration|enumeration]] of the different levels of stability that can exist for a particular kit. Kits marked with a stability rating of {{c|KitStabilityRating.PRIME}} will be tagged in the meta-repo JSON as being a "prime" kit and suitable for production use.
 
As you scroll down further, you will see some code like this:
 
{{file|name=foundations.py|lang=python|desc=foundations.py kit_groups|body=
class KitFoundation:
 
kit_groups = {
'prime': [
{'name': 'core-kit', 'branch': '1.0-prime', 'source': 'gentoo_prime_protected', 'default': True},
{'name': 'core-kit', 'branch': '1.1-prime', 'source': 'gentoo_prime_mk3_protected', 'stability': KitStabilityRating.DEPRECATED},
{'name': 'core-kit', 'branch': '1.2-prime', 'source': 'gentoo_prime_mk4_protected', 'stability': KitStabilityRating.BETA},
{'name': 'core-hw-kit', 'branch': 'master', 'source': 'funtoo_current', 'default': True},
{'name': 'security-kit', 'branch': '1.0-prime', 'source': 'gentoo_prime_protected', 'default': True},
{'name': 'security-kit', 'branch': '1.1-prime', 'source': 'gentoo_prime_mk3_protected', 'stability': KitStabilityRating.DEPRECATED},
{'name': 'security-kit', 'branch': '1.2-prime', 'source': 'gentoo_prime_mk4_protected', 'stability': KitStabilityRating.BETA},
{'name': 'xorg-kit', 'branch': '1.17-prime', 'source': 'funtoo_prime_xorg', 'default': False, 'stability': KitStabilityRating.PRIME},
{'name': 'xorg-kit', 'branch': '1.19-prime', 'source': 'funtoo_mk2_prime', 'default': True, 'stability': KitStabilityRating.PRIME},  # MK2
{'name': 'gnome-kit', 'branch': '3.20-prime', 'source': 'funtoo_prime_gnome', 'default': True},
{'name': 'gnome-kit', 'branch': '3.26-prime', 'source': 'funtoo_mk4_prime', 'default': False, 'stability': KitStabilityRating.DEV},
{'name': 'kde-kit', 'branch': '5.10-prime', 'source': 'funtoo_mk3_prime', 'default': False, 'stability': KitStabilityRating.DEPRECATED},
{'name': 'kde-kit', 'branch': '5.11-prime', 'source': 'funtoo_prime_kde', 'stability': KitStabilityRating.DEPRECATED},
{'name': 'kde-kit', 'branch': '5.12-prime', 'source': 'funtoo_prime_kde_late', 'default': True, 'stability': KitStabilityRating.PRIME},
{'name': 'media-kit', 'branch': '1.0-prime', 'source': 'funtoo_prime_media', 'default': False, 'stability': KitStabilityRating.DEPRECATED},
{'name': 'media-kit', 'branch': '1.1-prime', 'source': 'funtoo_mk3_prime', 'default': True, 'stability': KitStabilityRating.PRIME},  # MK3
{'name': 'media-kit', 'branch': '1.2-prime', 'source': 'funtoo_mk4_prime', 'stability': KitStabilityRating.BETA},
{'name': 'perl-kit', 'branch': '5.24-prime', 'source': 'funtoo_prime_perl', 'default': True},
{'name': 'perl-kit', 'branch': '5.26-prime', 'source': 'funtoo_mk3_prime', 'default': False, 'stability': KitStabilityRating.DEV},
{'name': 'python-modules-kit', 'branch': 'master', 'source': 'funtoo_current', 'default': True, 'stability': KitStabilityRating.PRIME},
}}
 
Here, we see the beginning of the definition of the {{c|KitFoundation}} class, which contains the {{c|kit_groups}} class variable. This variable, as you can see, defines a bunch of kits -- their name, the branch, a {{c|stability}} value that defines the stability rating of the kit, and other values. Note that if a kit is marked as {{c|default}}, it is assumed to have a kit stability rating of PRIME. You will also see that there is a {{c|source}} key, which defines the group of repositories and overlays that are used to create this kit.
 
Here are three important things to take away from this part of code: First, '''this is the official master definition of what kits exist, their stability rating, and what overlays/repositories are used to generate each kit.''' The next thing to take away from this code is that it is certainly possible to modify these settings for your custom meta-repo so that they are different from the Funtoo defaults.
 
Here is the third and most important thing about {{c|kit_groups}} -- the order that they are defined determines the order which the merge scripts try to match packages. The {{f|merge-scripts/package-sets}} files will be processed in order that the kits are defined in {{c|kit_groups}}, so {{c|core-kit}} first, {{c|security-kit}} second, etc. Once a catpkg has been added to a kit, it will not be added to any successive kits.
 
=== Going Deeper into Foundations.py ===
 
Moving right along, you will see a section of the {{c|KitFoundation}} class that looks like this:
 
{{file|name=foundations.py|lang=python|desc=foundations.py python_kit_settings|body=
python_kit_settings = {
# branch / primary python / alternate python / python mask (if any)
'master': {
"primary": "python3_6",
"alternate": "python2_7",
"mask": None
},
'3.4-prime': {
"primary": "python3_4",
"alternate": "python2_7",
"mask": ">=dev-lang/python-3.5"
},
'3.6-prime': {
"primary": "python3_6",
"alternate": "python2_7",
"mask": ">=dev-lang/python-3.7"
},
'3.6.3-prime': {
"primary": "python3_6",
"alternate": "python2_7",
"mask": ">=dev-lang/python-3.7"
}
}
}}
}}


This section is used to define special settings for python-kit. Specifically, for each branch of python-kit, it defines the primary version of python that we will attempt to use to satisfy python-single USE dependencies, followed by an alternate value to use if the ebuild does not support the first. We can also specify a mask to be injected into each python-kit to mask certain versions of python that should be masked due to lack of support in that kit.
[[Category:Official Documentation]]
 
[[Category:Development]]
=== Foundations.py Kit Source Definitons ===
 
Next, we have a section that looks like this:
 
{{file|name=foundations.py|lang=python|desc=foundations.py kit_source_defs|body=
kit_source_defs = {
"funtoo_current": [
{"repo": "flora"},
{"repo": "faustoo"},
{"repo": "fusion809"},
{"repo": "gentoo-staging"}
],
"funtoo_mk2_prime": [
{"repo": "flora", },
{"repo": "faustoo"},
{"repo": "fusion809", "src_sha1": "489b46557d306e93e6dc58c11e7c1da52abd34b0", 'date': '31 Aug 2017'},
{"repo": "gentoo-staging", "src_sha1": '80d2f3782e7f351855664919d679e94a95793a06', 'date': '31 Aug 2017'},
# add current gentoo-staging to catch any new ebuilds that are not yet in our snapshot above (dev-foo/* match)
{"repo": "gentoo-staging-underlay"},
],
"funtoo_mk3_prime": [
{"repo": "flora", },
{"repo": "faustoo", },
{"repo": "fusion809", "src_sha1": "8733034816d3932486cb593db2dfbfbc7577e28b", 'date': '09 Oct 2017'},
{"repo": "gentoo-staging", "src_sha1": '2de4b388863ab0dbbd291422aa556c9de646f1ff', 'date': '10 Oct 2017'},
{"repo": "gentoo-staging-underlay"},
], ...
}}
 
This section contains definitions of various overlay stacks, called "kit sources". Kit sources are a combination of overlays, arranged in a python list ({{c|<nowiki>[ ]</nowiki>}}). A kit source serves as a unified collection of source catpkgs for a particular kit. Each kit can have one kit source. Kit sources ''may'' be shared among kits for consistency purposes, and to avoid duplication and to help organization. Note that this is where we specify branch or SHA1 that is used for each overlay. If no SHA1 is specified, the merge scripts will use the top commit of master as the source for that overlay (ie. the overlay will track upstream.)
 
{{Note|A "catpkg" is a category/package combination, like {{c|sys-apps/portage}}, with no version information. When we match catpkgs, we look for a cat/pkg directory in the overlay, and if we find a match, we grab the full contents of the catpkg directory from the overlay, and ignore any other occurrence of the same catpkg in other overlays. When we talk of "package-set" rules below, we are referring to text files that define what catpkgs go into what kits. We can specify catpkgs literally or use patterns and other approaches to select catpkgs destined for a particular kit. The merge scripts uses these package-set rules files to define what goes in each kit. But where they search for each catpkg is defined in {{f|foundations.py}}, above.}}
 
Currently, package-set rules (see note above) are applied in
the same order that the overlay appears in the {{c|kit_source_defs list}} -- so for "funtoo_current", package-set rules -- an attempt to match catpkg patterns for a kit -- will
be applied to flora first, then faustoo, then fusion809, etc, with gentoo-staging searched last. In theory, this would allow any "upper" overlay to override catpkgs in later-appearing overlays. However, this is not the case, because the "upper" overlays are generally "locked down" so that they are only ''allowed to provide a particular set of catpkgs'', or are allowed to provide any catpkg as long as it doesn't appear in Gentoo, for example. So in actual practice, gentoo-staging is set up to have the higher priority, even though it is searched for matches later. Also notice that newer kit source definitions now have a "bottom" gentoo-staging-underlay definition that has a special purpose -- to allow us to grab new Gentoo catpkgs that aren't in our snapshotted gentoo-staging repository yet. This works because gentoo-staging-underlay tracks upstream master, while gentoo-staging is locked to a particular point in the past. This way we get brand-new gentoo catpkgs, but existing gentoo catpkgs stay locked to a particular point in time.
 
=== Completing the Deep Dive ===
 
Our deep dive into the functionality of {{f|foundations.py}} is almost complete -- just one more part to go! You will notice the following code at the end of the file:
 
{{file|name=foundations.py|lang=python|desc=foundations.py overlay definitions|body=
@property
def overlays(self):
return {
# use gentoo-staging-2017 dirname to avoid conflicts with ports-2012 generation
"gentoo-staging": {"url": self.config.gentoo_staging, "dirname": "gentoo-staging-2017"},
"gentoo-staging-underlay": {"url": self.config.gentoo_staging, "dirname": "gentoo-staging-2017-underlay"},
"faustoo": {"url": "https://github.com/fmoro/faustoo.git", "eclasses": [
"waf",
"googlecode"
],
            # SKIP any catpkgs that also exist in gentoo-staging (like nvidia-drivers). All others will be copied.
            "filter": ["gentoo-staging"],
            # well, I lied. There are some catpkgs that exist in gentoo-staging that we DO want to copy. These are the
            # ones we will copy. We need to specify each one. This list may change over time as faustoo/gentoo gets stale.
            "force": [
            "dev-java/maven-bin",
            "dev-java/sun-java3d-bin",
            "dev-php/pecl-mongo",
            "dev-php/pecl-mongodb",
            "dev-python/mongoengine",
            "dev-python/pymongo",
            "dev-util/idea-community",
            "dev-util/webstorm",
            "x11-wm/blackbox"
            ]
            },
"fusion809": {"url": "https://github.com/fusion809/fusion809-overlay.git", "select": [
"app-editors/atom-bin",
"app-editors/notepadqq",
"app-editors/bluefish",
"app-editors/textadept",
"app-editors/scite",
"app-editors/gvim",
"app-editors/vim",
"app-editors/vim-core",
"app-editors/sublime-text"
]
              },  # FL-3633, FL-3663, FL-3776
"plex": {"url": "https://github.com/Ghent/funtoo-plex.git", "select": [
"media-tv/plex-media-server",
],
        },
# damex's deadbeef (music player like foobar2000) overlay
"deadbeef": {"url": "https://github.com/damex/deadbeef-overlay.git", "copyfiles": {
"profiles/package.mask": "profiles/package.mask/deadbeef.mask"
},
            },
# damex's wmfs (window manager from scratch) overlay
"wmfs": {"url": "https://github.com/damex/wmfs-overlay.git", "copyfiles": {
"profiles/package.mask": "profiles/package.mask/wmfs.mask"
},
        },
"flora": {"url": self.config.flora, "copyfiles": {
"licenses/renoise-EULA": "licenses/renoise-EULA"
},
          },
}
}}
 
This section of {{f|foundations.py}} declares the names for the actual overlays themselves, where we can clone them from, and also helps us answer the question of which overlay has priority over another. In the case of the fusion809 overlay, for example, we will only grab a select set of catpkgs, specified in the {{c|select}} list. Whereas in the faustoo overlay, we will force the merge scripts to grab updates the the catpkgs listed in the {{c|force}} list, but ''skip'' any catpkgs in faustoo that also appear in our gentoo-staging snapshot. All these special rules define ''exceptions'' to the normal processing logic of the merge scripts, which will look for catpkg matches in the first overlay listed in the kit source definition, before proceeding to the second, etc.
 
=== Wrapping Up Foundations.py ===
 
We certainly have a lot of levers we can use to control what gets included in a particular kit. Using {{f|foundations.py}}, we can add or remove overlays we want to use, and we can also alter the order they are scanned by the merge scripts. We can control what snapshots are used, and vary this on a per-kit basis. And in the overlay definitions, we can also create exceptions to the normal processing order, to effectively prioritize gentoo catpkgs over overlay catpkgs, even if the overlays are processed first. Or we can limit the scope of what catpkgs we scan a particular overlay for, or force certain catpkgs to be copied from a particular overlay if we ''know'' we want those particular ones.
 
All that is left to cover are the package-set rules, which define which catpkgs go into each kit, and kit-fixups, which allow us to have Funtoo overrides for any catpkgs we want. We'll cover those topics next.
 
== Package Sets ==
 
'''Package sets''' define which catpkgs go in which kits. The package set files are located at {{c|kit-fixups/package-sets}}. They can either consist of a single file named {{c|(kit)-packages}} or a directory with the same name. In the case of a directory, all of the files inside the directory are concatenated and used as a package set.
 
=== Package Set Format ===
 
Package sets are a text-based format that consist of one catpkg entry per line. Let's look at the various types of package sets entries:
 
{{TableStart}}
<tr><th>Entry type</th><th>Example</th><th>Explanation</th></tr>
<tr><td>literal</td><td>{{c|sys-apps/portage}}</td><td>Specify a single catpkg by exact name.</td></tr>
<tr><td>category wildcard</td><td>{{c|sys-apps/*}}</td><td>Specify all packages that appear in a particular category.</td></tr>
<tr><td>category wildcard with exceptions</td><td>{{c|sys-apps/* -sys-apps/foo -sys-apps/bar}}</td><td>Specify all packages that appear in a particular category, with some exceptions.</td></tr>
<tr><td>regex</td><td>{{c|sys-.*/foo.*}}</td><td>Specify all catpkgs that match a particular regex.</td></tr>
<tr><td>dependencies in category</td><td>{{c|@depsincat@:x11-base/xorg-x11:media-fonts}}</td><td>In this example, anything in the {{c|media-fonts}} category that has dependencies upon {{c|x11-base/xorg-x11}}.</td></tr>
<tr><td>maintainer</td><td>{{c|@maintainer@:dev-lang:ml@gentoo.org}}</td><td>In this example, all {{c|dev-lang}} packages that have a maintainer of {{c|ml@gentoo.org}}.</td></tr>
<tr><td>has eclass</td><td>{{c|@has_eclass@:kde5}}</td><td>In this example, all catpkgs that use an eclass of {{c|kde5.eclass}}.</td></tr>
<tr><td>category has eclass</td><td>{{c|@cat_has_eclass@:x11-apps:xorg-2}}</td><td>In this example, all catpkgs in the {{c|x11-apps}} category that use an eclass of {{c|xorg-2.eclass}}.</td></tr>
{{TableEnd}}
 
=== Package Sets -- Putting It All Together ===
 
Here are some important facts about package sets:
 
# Package set matches are executed in a particular order, and this order is defined by the order of kits in {{c|kit_groups}} in {{c|foundations.py}}.
# Once a catpkg is matched during processing of a kit, that catpkg is assigned to that kit, and cannot appear in another kit.
# If a catpkg is included in a particular branch of a kit, then that catpkg will appear in all branches of that kit, assuming it is available.
# Each kit and branch defined in {{c|kit_groups}} specifies a "source" -- an entry in {{c|kit_source_defs}} which in turn defines a stack of repositories/overlays and associated SHA1 commits to use as sources for catpkgs.
 
So, here's how the package set processing would begin. If we look at {{c|kit_groups}} in {{c|foundations.py}}, we see that core-kit 1.0-prime is listed first. So we will look for catpkg matches for core-kit 1.0-prime using the {{c|kit-fixups/package-sets/core-kit-packages}} package set directory. We will apply these match rules against the {{c|gentoo_prime_protected}} kit source definition, and we will look for matches in each repository in the order listed in the {{c|kit_source_defs}} entry. The first match we find will be used as the source catpkg. But remember that we have specific rules in place, defined in the {{c|overlays}} property, that effectively gives gentoo-staging priority for most of the catpkgs.
 
After this is done, we will then process core-kit 1.2-prime, since 1.1-prime is deprecated and will be skipped, and then continue to core-hw-kit, and continue to work down the {{c|kit_groups}} list. This process will build up a set of catpkgs that will appear in each kit.
 
== Kit-Fixups ==
 
And finally, we have saved a very key part of the kit generation process for last. The {{c|kit-fixups}} repository is so named because it contains ''fixups'', which are forked Funtoo catpkgs that are used to override catpkgs that appear in the upstream overlays and repositories. They have a special structure. We will look at the structure of the core-kit fixup directory, although others will follow the same model:
 
{{TableStart}}
<tr><th>CatPkg Path</th><th>Description</th></tr>
<tr><td>{{f|kit-fixups/core-kit/global/sys-apps/portage}}</td><td>Due to the {{c|global}} directory, this catpkg will always be used when a package set specifies a match for {{c|sys-apps/portage}}, for '''all''' branches of core-kit.</td></tr>
<tr><td>{{f|kit-fixups/core-kit/curated/sys-apps/portage}}</td><td>Due to the {{c|curated}} directory, this catpkg will always be used when a package set specifies a match for {{c|sys-apps/portage}}, for '''all''' branches of core-kit '''except a master branch.'''</td></tr>
<tr><td>{{f|kit-fixups/core-kit/1.2-prime/sys-apps/portage}}</td><td>Due to the {{c|1.2-prime}} directory, this catpkg will always be used when a package set specifies a match for {{c|sys-apps/portage}}, for the '''1.2-prime''' branch of core-kit only.</td></tr>
{{TableEnd}}
 
Remember that kit-fixups is designed so that ''a fixup will always override any upstream packages.'' This makes it easy to keep track of Funtoo-maintained core packages. And also note that the flora repository should be used for "bonus" packages while kit-fixups should focus more on forks of critical system packages and bug fixes for Funtoo. This way, we can keep contributed ebuilds separate from core operating system ebuilds and associated bug fixes for upstream issues.

Latest revision as of 21:47, June 8, 2022

   Important

These pages are out of date. Please see the latest Funtoo:Metatools page for usage information.

Overview

Funtoo Linux uses "merge scripts" to create its kits and update meta-repo. These scripts work by sourcing ebuilds from various overlays, and combining them using special algorithms to yield the kits you use. A meta-repo is also generated, which points to the specific kits generated that are designed to work together.

Before starting, please read and understand the following pages:

Different Approaches

merge-all-kits can be used in a variety of ways. If you are an individual developer, you may want to use merge-all-kits in developer mode, which is its default mode. Developer mode makes it easy to generate a meta-repo and kits that you can test locally.

In developer mode, a meta-repo and all automatically-generated kit git repositories are created from scratch. These git repositories will have no remotes, so they will simply exist locally on disk, and they will not have any history shared with the Funtoo project. It you look at the commit history for the kits and meta-repo, you will see that they essentially have no history.

Another way to use merge-all-kits is with gitolite as a remote, which is documented under the Gitolite Setup sub-page. Using this configuration, merge-all-kits will write all of its destination git repositories to gitolite. You can then configure other systems to ego sync from gitolite as a source. This can be good in a distributed development environment. This method can also be used to create a meta-repo and kits that diverge from Funtoo's kit but still connect to its history.

Finally, the merge-all-kits script can be run in a production mode, which is very similar to using it with gitolite except that you may be pushing up your destination meta-repo and kits to a public location like GitHub or GitLab.

When first starting out with merge-all-kits, you should definitely start with developer mode and see if that meets your needs first.

Getting The Code

You can find the code that does this on code.funtoo.org, housed at code.funtoo.org. The script that does all the heavy-lifting is called merge-all-kits. Let's clone it from git, on the machine that will be generating new kits and meta-repo:

user $ git clone https://code.funtoo.org/bitbucket/scm/core/merge-scripts.git

You will also want to install the following dependencies so that the code can run:

root # emerge jinja lxml

Configuration and Paths

In general, you should run merge-all-kits as a regular user, and this user needs to be a member of the portage group.

In the user's home directory, create a ~/.merge directory with the following contents:

   /root/.merge
[sources]

flora = https://code.funtoo.org/bitbucket/scm/co/flora.git
kit-fixups = https://code.funtoo.org/bitbucket/scm/co/flora.git
gentoo-staging = https://code.funtoo.org/bitbucket/scm/auto/gentoo-staging.git

[branches]

flora = master
kit-fixups = master
meta-repo = master

By default, merge-all-kits will create a ~/repo_tmp directory where it will store all of its work. Inside ~/repo_tmp/source-trees, source git trees that will be used to generate meta-repo will be cloned. Inside ~/repo_tmp/dest-trees, git repositories will be created to write results into. The meta-repo will be stored at /~repo_temp/dest-trees/meta-repo, and in developer mode, the kits will be stored in meta-repo, at ~/repo_tmp/dest-trees/meta-repo/kits, so that meta-repo is configured 'ready to use' at it would appear at /var/git/meta-repo. When 'production' mode is specified via the --prod switch, the meta-repo will not have kits stacked inside it but instead the kits will be written directly into ~/repo_tmp/dest-trees.

A metadata cache will also be created and stored at ~/repo_tmp/metadata-cache, and your user must be a member of the portage group for merge-all-scripts to be able to properly generate the metadata cache.

Running Merge-All-Kits

To run merge-all-kits, use it as follows:

user $ path/to/merge-scripts/bin/merge-all-kits 1.4-release

The script will then run, and it will git clone flora, kit-fixups and gentoo-staging from the URIs in the ~/.merge file, and assemble them into a complete meta-repo. The meta-repo will be located at $HOME/repo_tmp/dest-trees/meta-repo.

To use the meta-repo for testing, you can add the following lines to /etc/ego.conf:

   /etc/ego.conf
[global]
meta_repo_path = /home/user/repo_tmp/dest-trees/meta-repo

Then, using ego 2.8.0 or later, run the following command:

root # ego sync --in-place

This will ensure that the proper kit branches in your meta-repo are checked out and that all the repos.conf and profiles files in /etc/portage are configured correctly for your repository to be used. Note that no actual "git pull" will be performed -- this is intentional and a special feature of the --in-place option -- because your local git repositories have no remotes to pull from and contain all the information they need to be used.

You're now ready to use your meta-repo directly:

root # emerge foo