This document answers some frequently-asked questions (FAQ's) about Mezzanine. Use the table of contents below to find the question that pertains to your situation, or browse through all the questions in order.
Mezzanine is a set of tools, mostly written in Perl, which simplify and expedite the tasks involved with creating and maintaining a software product. This is mostly used in the creation of the underground Linux distribution called Vermillion, but it can be applied to any product of any nature or size.
Currently only RPM/SRPM packages are supported, along with Mezzanine's own custom SPM and FST formats for helping RPM and CVS work together well. Further, it has only been tested with Red Hat's distribution of Linux, but in theory it should work with any RPM-based distro.
Mezzanine was written by Michael Jennings, also known as "KainX" on IRC and "mej" via e-mail or in person. He is also responsible for Eterm, a terminal emulator for the X Window System; libast, a small library of handy functions; and Vermillion, the custom RedHat-based Linux distribution.
Mezzanine makes maintaining software packages much easier. Specifically, it automates the processes of importing packages into source code control, creating patch files for changes to the base source, building products and their component packages, creating installation media for products, and so forth.
If you have a RedHat-based Linux system and have tried downloading and building SRPM's from other places, you have likely experienced the difficulty of patching the source and adding those patches to the SRPM. Mezzanine makes this very easy.
Well, there are two answers to this question, really. The first answer explains why I originally went with RedHat. After using Debian for awhile at 3Com and when I first arrived at VA Linux, I grew extremely annoyed and frustrated with dselect, dpkg, and apt. VA was still selling servers back then, and they all came pre-loaded with a custom version of RedHat.
When my frustration level finally reached critical, I switched over to VA's custom distro (VA Linux 6.1.1 at the time). I never looked back. It worked exactly the way I wanted it to, and it took me no time at all to learn the in's and out's of RPM packaging.
Eventually, I began maintaining VA's distro myself. It soon got a name change due to RedHat lawyers throwing a hissy fit; it was henceforth known as "Red Hat Linux with VA Linux Enhancements," or "RH-VALE." (It was originally "RH/VALE," but you can't use '/' in filenames....)
Now, for the second part of this question: Why did I stick with RedHat? The RPM-based philosophy is far more compatible with this type of development. The Debian community, especially the group of developers, are largely zealots who do not feel that individuals or small groups should be creating and releasing their own .deb packages. Furthermore, IMHO, Debian has its head fairly well entrenched in RMS's posterior; RMS has long since lost sight of the true vision and goal, preferring instead to focus on ego-centric concerns, and I refuse to be party to his religious activism.
Yes, there are other RPM-based distro's. I don't really have a problem with Linux-Mandrake, as they seem to do a much better job at keeping up with package updates in a stable, useable manner. I refuse to use SuSe due to the unfortunate fascist nature of its YaST config tool.
First and foremost, however, I use RedHat because it's the distro with which I am most familiar and about which I have the most knowledge and expertise. In the end, it all boils down to that.
There are currently hooks in place for Debian support. I do not use Debian, nor do I use dpkg, so I have no fleshed out the backend code for those sections yet. In theory, it shouldn't be too much work; the biggest problem will be the fact that the creators of dpkg elected to not have a true source package format (a la SRPM).
Mezzanine provides a series of wrappers around source code management. Currently, the only interface which has been fleshed out is the CVS one, but others could easily be added.
SCM tools can be flexible and powerful, but that also means they tend to complicate the simpler things. Mezzanine has several tools that streamline and automate the most common SCM tasks.
The following Mezzanine commands directly manipulate the SCM repository. Although other Mezzanine commands also interact with the repository, they use these basic operations to do so.
Table 1. Mezzanine SCM Command Summary
mzadd | Mark new files for inclusion in repository |
mzdiff | Generate a diff between current source and repository |
mzget | Download latest source from repository |
mzlog | View log of changes to one or more files |
mzlogin | Login to the repository |
mzput | Upload any changes in your local source to the repository |
mzreset | Remove any persistent meta-information (tags, dates) in local source |
mzrm | Mark files for removal from repository |
mzrtag | Symbolically tag repository sources |
mzstat | Obtain status information on file(s) |
mztag | Symbolically tag local sources |
Note that there are other Mezzanine commands that also interact with the repository. However, they are not simply encapsulated repository operations, so they are not listed here. |
---|
All the repository commands in the table above share a common interface. This allows you to combine certain operations so that you can do things more efficiently. This is especially obvious in this particular scenario.
Let's say you want to use Mezzanine to obtain the latest CVS
sources for Eterm, but your
$CVSROOT
is already setup for a different
repository. We'll furthermore assume that you have never
obtained these sources before, and that you want to do so
anonymously. Using CVS directly, you would enter:
cvs -d :pserver:anonymous@cvs.enlightenment.sourceforge.net:/cvsroot/enlightenment login cvs -d :pserver:anonymous@cvs.enlightenment.sourceforge.net:/cvsroot/enlightenment co eterm
However, Mezzanine will allow you to combine the two steps into one. It will even check your ~/.cvspass to see if you actually need to perform the "login" or not. The command is:
mzget -lD :pserver:anonymous@cvs.enlightenment.sourceforge.net:/cvsroot/enlightenment eterm
The -l option causes a login to be performed if needed. It does not take any options, so the -D option may follow it immediately without needing another -. The -D option specifies a repository other than the default; in this case, the Enlightenment CVS repository. The rest of the command line (which is simply "eterm" in this example, but could contain as many names as desired) consists of the names of modules to download.
As you may have noticed, the mzput command actually does a lot more than just upload your changes to the repository. For example, the very first thing it does (by default; use the --blind option to override this) is download an update from the repository to make sure that there are no conflicts and that you have the latest changes. If any conflicts are found, the upload will not even be attempted (since it would fail anyway).
If the update is successful,
mzput will note the date/time,
your userid, and your name (assuming it's in the GECOS
field), and will create a template for a ChangeLog entry.
It will then open this template in an editor (chosen from
$EDITOR
) for you to fill in. It will not
permit an empty ChangeLog message; in fact, if nothing is
added to the template, the upload will be aborted.
After you save your ChangeLog entry and exit the editor, the contents of the template will be appended to the ChangeLog file in the current directory (it will be created and added to the upload if not present) followed by a separator line. The ChangeLog file is then added to the list of files to upload, and the upload is performed.
It is common for developers to want to add or remove files and upload them at the same time. By default, if any file or directory names are specified on the mzput command line, only those files/directories will be uploaded. However, if the -a option is specified (e.g., mzput -a file1 file2 file3), a general upload will be done, and the files/directories listed on the command line will be added to the repository. This is a shorter way of accomplishing the same task as:
mzadd file1 file2 file3 mzput
The -r option may be used in an identical fashion to remove files and upload changes to the repository (e.g., mzrm file1 file2 file3, a shortcut for
mzrm file1 file2 file3 mzput
You may additionally specify the -x option to indicate that only those files which have been added/removed should be synced to the repository. Furthermore, -x by itself as an option to mzput indicates that the ChangeLog file should be neither appended to, nor created, nor uploaded.
Table 2. Mezzanine SCM "Put" Command Summary
mzput | Upload all changes to the repository, and append ChangeLog entry. |
mzput file1 file2 ... | Upload only specified file(s) if changed (including ChangeLog entry). |
mzput -a file1 file2 ... | Add specified file(s) and upload all changes (w/ ChangeLog). |
mzput -r file1 file2 ... | Remove specified file(s) and upload all changes (w/ ChangeLog). |
mzput -x | Upload all changes without appending ChangeLog entry. |
mzput -x file1 file2 ... | Upload only specified file(s) (no ChangeLog entry). |
mzput -x -a file1 file2 ... | Add and upload specified file(s) only (w/o ChangeLog). |
mzput -x -r file1 file2 ... | Remove and upload specified file(s) only (w/o ChangeLog). |
The first step is to determine whether or not you want to create the branch from the sources you have locally, or if you want to branch off from the head of the main trunk of the repository. That will determine whether you use mztag (for the former case) or mzrtag (for the latter case). For purposes of this example, I'll use the former case, but tagging the repository directly (other than the extra r) isn't any different.
Next, you need to choose the tag you want. Tags should contain uppercase letters, underscores, and hyphens only. I highly recommend tagging things using the package name and version number, replacing spaces with hyphens and dots with underscores. For example, if you were to be tagging version 0.9.1 of Eterm, use the tag ETERM-0_9_1. This makes translating back and forth between tags and package/version pairs easy.
Last, note the use of the -b option, which signifies that a branch should be created using the specified tag as its name. And finally, the command:
mztag -b FOO-1_0
This command will create a new branch with the specified tag. If you want to work on the created branch, make sure you immediately follow the above command with:
mzget -t FOO-1_0
Though some SCM systems may do this for you, some may not. Better to get in the habit of it to be on the safe side.
Like any system, some rather complex concepts are more easily described by agreed-upon terminology. As Mezzanine has a fairly unique view of software products and their components, I had to come up with some way of describing that view. And thus were born some new TLA's (including one XTLA).
When you drill down on a product, through all the layers of products and sub-products, you wind up with a big (or small, as the case may be) list of packages that make up that product. From the perspective of the overall product build (i.e., buildtool), a package is a package. However, the underlying build routines distinguish between several different types of packages, some of which actually require building, and others which only need to be moved into place.
From the packager's perspective, there are generally two types of packages: source packages and binary packages. From a buildmaster/build system perspective, there are also two types of packages: those that are built from source into binaries and those that aren't. For purposes of building, Mezzanine recognizes the following 4 types of buildable packages:
Table 3. Mezzanine Buildable Package Types
Source Package | This term refers to a single file which contains all source and instructions necessary to build the package. Specifically, this refers to an SRPM or a tarball containing a spec file. |
Source Package Module (SPM) | In order to maintain a source package under SCM, it is "exploded" into a directory structure which Mezzanine understands. This directory structure is called an SPM (not to be confused with SRPM). The SPM contains three directories: S, which contains the source file(s); P, which holds the patches to be applied to the original vendor source; and F, which contains the spec file or other build instructions. Running mzimport on an SRPM will give you an SPM. You can then use other Mezzanine commands to manipulate the SPM to create patches, run a build of the package, etc. |
Full Source Tree (FST) | Back in the early days of Mezzanine (then called "Avalon"), the unarchived (untarred) vendor source was imported into SCM just like a normal source tree. Then each subsequent patch to the source was made, tagged, and checked in. The build process involved building the original source tarball (based on a tag and instructions held in the SRCS package variable in the prod file), creating each patch one-by-one (using mzdiff and the patch tags), then moving everything into place so that rpm -ba could generate the needed binary and source packages. Although this approach was an interesting one, it proved cumbersome and was largely abandoned. Mezzanine still supports it, largely because Mezzanine itself is still maintained as an FST. |
Custom-built Full Source Tree (CFST) | The "Custom-built" part means that the package is responsible for building itself (rather than Mezzanine building it). The CFST contains a file called Makefile.mezz which contains all commands required to generate the source tarball, spec file, and/or patches, and build source and binary package files from them. Mezzanine invokes the make command and provides some basic variables telling what it wants and where it expects things to end up; the rest is entirely up to the package. This technique is most valuable for projects that are already maintained under SCM and would like Mezzanine to be able to build the packages from the original project source tree. (The filename was chosen such that its purpose would be clear without interfering with the normal build process of existing applications.) |
As you can see, the terms are important shorthand for describing fairly involved concepts concisely.
Short answer: Import it!
The mzimport tool is designed to help you get a package into SCM and ready for modification. The simplest way to import a package is to get an SRPM (e.g., from FreshRPM's or RPMFind) and import that. Mezzanine will automatically turn the SRPM into an SPM for you, after which the directory tree is imported into the repository.
Let's say, for example, you've gone out on the Interweb and found yourself an SRPM for the "pile sarnet" package (which, as everyone knows, is required for a system to be functional). You've downloaded pile-sarnet-1.0.7-3.src.rpm and you want to get it into your tree. Here's how you do it:
mzimport pile-sarnet-1.0.7-3.src.rpm
Yep, that's it. Mezzanine does everything automatically. NOTE: if you don't have a repository or aren't connected to the network, you can still use Mezzanine to modify the package. Simply specify the -L (local mode) option to prevent Mezzanine from trying to talk to a repository. The following command will create an SPM called pile-sarnet in your current directory:
mzimport -L pile-sarnet-1.0.7-3.src.rpm
The local mode flag can also be used with the other commands in this section, excluding (obviously) those like mzget and mzput which are intended solely to interact with the repository.
As another example, let's assume you used local mode to create an SPM on your workstation, but now you want to import it into the SCM repository. It's still pretty easy; you just need to supply one more piece of information.
You see, if you have an SRPM, Mezzanine can determine the package name and version from the filename. It doesn't currently go digging inside the directory tree for spec files, though, so you have to supply that information when you import a directory tree. So, assuming you're in the top-level directory of what you want to check in, the command is:
mzimport -n pile-sarnet-1.0.7
(If you're not in that directory, simply add the path to it at the end of the command line above.)
This is where Mezzanine really shines. Without it, generating a patch involves installing the SRPM, untarring the source, applying all the other patches, patching the source, repeating steps 2 and 3 in another location, generating a diff between the two, putting it in the right place, adding it to the spec file as a patch, and building from the spec file and sources again. A long, tedious process. Thankfully, Mezzanine automates much of it.
The first step is to download the SRPM and import it, or do whatever you need to do to make it into an SPM. And if you imported it, you'll want to check it out again so you can work on the copy of it that's under SCM. For the rest of this section, I'll assume you're not using local mode (-L); if you are, make sure to add that option to the mzpatch command also.
First, cd into your SCM's top directory (the one that contains the F, P, and S subdirectories). Then run mzprep. This will create a fully-patched version of the unarchived source in a directory called work. Make your changes to the source in that directory.
Once you've made your changes, you'll want to turn them into a patch. Run mzpatch -n <patch>, where <patch> is the name you want your new patch to have. Mezzanine will generate the patch and place it in the P directory for you. Then, all you have to do is add it to the spec file! (Don't forget the %patch -p1 macro, and to update the release number!)
When you've updated the spec file, the mzbuild command will allow you to build the package with your new patch included. If it works, you'll get a new set of packages in the top-level SPM directory. If needed, use mzput to commit your changes (after testing the packages first, of course). And you're done!
For the sake of furthering this discussion, let's say your patch doesn't quite work the way you wanted it to. If you re-run mzprep, you'll get a new working tree with your patch already applied. Make whatever alterations you need to, then regenerate the patch using the command mzpatch -n <patch_num>, where <patch_num> is the patch number you assigned to your patch in the spec file. Mezzanine will automatically re-generate the patch for you, merging your previous changes with the new ones.
A complete example:
mzget pile-sarnet cd pile-sarnet mzprep ...make code changes... mzpatch -n pile-sarnet-1.0.7-somebody_screwed_up.patch ...edit spec file to put in Patch1000... mzbuild mzprep ...make more changes... mzpatch -n 1000 mzbuild
(Please note that the stuff enclosed in ellipses ("...") are editorial comments, NOT commands.)
As mentioned in the previous example, if you're inside the package directory, simply running mzbuild will do the trick. If not, or if the package you want to build is an SRPM or something, simply give the path to the package (e.g., mzbuild pile-sarnet-1.0.7-3.src.rpm).