The Linux Page

Basics about Drupal Development

GIT

Drupal now offers git to access its source code and 3rd party modules, themes, etc.

The GIT system is interesting but it has a huge difference between the CVS and SVN scheme: it requires an action, such as commit, and a push. The push is what synchronize your copy with the repository. Without the push, all the actions you've been taking will have no effect (they only are on your hard drive.)

As you will see in each project, there is a Version Control tab at the top. Clicking on it gives you most of the instructions you need to know to work with Drupal git. I will not repeat them here. The only two things I often do is commit + push and tagging (to create new official versions.)

Branching

The correct way to create a new branch is simple. You start with the latest version and then use the -b option of the checkout command like this:

git clone --branch 6.x-1.x <user>@git.drupal.org:project/<project>.git
git checkout -b 7.x-1.x
git push -u origin 7.x-1.x

Note that the very first branch (i.e. when creating 6.x-1.x) requires (1) a first commit + push in the master branch; and (2) a copy (rename) of the master branch. This copy is done with the branch command and the -m flag as in:

git branch -m master 6.x-1.x

If like me you first created a tag instead of a branch, then you messed up your tree. You will have to delete the tag and push the deletion. Because it is a delete, the push in this case looks weird.

git tag 7.x-1.x-dev
git push -u origin 
...
git tag -d 7.x-1.x-dev
git push origin :refs/tags/7.x-1.x

As you can see, if you add a tag (instead of a branch) for 7.x-1.x-dev, then you need to delete the tag with the -d option. But the tag as probably been pushed in by other instructions and to remove it you need to push that special named reference...

GIT Details

GIT offers an HTTP interface with a lot of information about the repository. For example, for the menu_per_role module, you can find details here:

http://cgit.drupalcode.org/menu_per_role (replace menu_per_role with the name of your project)

It lists all the tags, logs, commits, diffs, etc.

This can be very useful if you did something and are not too sure what you did. Not that until you do a push, what you did has no meaning in the repository itself. If you want to cancel all your actions you can simply restart from the repository (i.e. delete your existing folders, then use the "git clone ..." command to restart from a fresh version.)

CVS

Read-only CVS

The CVS tool uses a URL to connect to a server and retrieve files. If you used the default "cvs co" as defined on a site, then it is more than likely that it will create a read-only set of folders.

CVS creates a folder named CVS (all in caps, important under Unix!) That folder includes the necessary information for CVS to connect to the repository and read/write data. One of the files defined in this folder is called Root. This is where the URL is saved.

The CVS URL is composed of several parts:

  1. Server type (often pserver)
  2. Login name (likely anonymous if you can only read the data)
  3. Password (usually, also anonymous)--optional in some cases
  4. Domain name (often starts with cvs, it is cvs.drupal.org for Drupal)
  5. Path to the files repository

When you need to read and write, you do not need to re-read the entire folder from the repository. Instead you can simply edit the Root file and change the URL line.

For instance, for Drupal, you would use something like this:

Read Only version

	:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal-contrib

Read/Write version

	:pserver:alexiswilke@cvs.drupal.org:/cvs/drupal-contrib

Notice that you simply replace the anonymous:anonymous into your Drupal login name. Then you will need to login with CVS. This is done with cvs login. That will ask you your login name and password (remember that your CVS password is likely different from your Drupal page password.)

Once logged in, go to the right directory and type "cvs commit" to write your changes (you may need to run cvs update once to make CVS happy.)

Checkout command for Drupal in HEAD:

  CVSROOT=:pserver:anonymous:anonymous@cvs.drupal.org:/cvs/drupal cvs co drupal

Basics

If you never used CVS before, there are a few things about how to use it. The following expects you are in the folder where you have your source files.

Add a file in the repository:

	cvs add <filename>

This works with regular files and folders. Be very careful with folders, you CANNOT delete them without having direct access to the CVS system.

Once in a while, you will get errors that get fixed using the following:

	cvs update

The update command is also used in case you have other people working on the same project. Their changes need to be checked out (updated). This ensures you get a chance to fix failing merges.

To remove a file (does not work with folders...) you first need to delete the file in your current folder, then use the remove command.

	rm <filename>
	cvs remove <filename>
	cvs commit

Note that the remove is not commited immediately (you can cancel the rm ... with a cvs update)

To save your changes in the CVS, use the commit command.

	cvs commit [<filename>]

The filename is optional. When not specified, all the files that have changed, were added, etc. are commited. If you want to first check your changes (to verify once more that you made no mistake) then use the diff command:

	cvs diff [<filename>]

For more information, try cvs help or search for the CVS detailed documentation on the net.

More advance CVS instructions from the Drupal guys themselves: http://groups.drupal.org/node/14944

CVS Branching

I wanted to create a new branch for one of the module I'm working on to get a version 7.x going. I used the following from someone who posted on the link I gave at the end of the previous chapter.

  $ cvs checkout contributions/modules/foo  # Retrieve HEAD
  $ cd foo
  $ cvs update -j DRUPAL-6--1   # Merge branch over head
  $ cvs diff -up
  $ cvs commit -m "Merged dev branch back into HEAD" # Check the merged branch back in.
  $ cvs tag -b DRUPAL-6--2

If you are not working from the head, you may want to do a cvs checkout from your current branch directly:

  $ cvs checkout -r DRUPAL-6--1 contributions/modules/foo
  $ cd foo
  $ cvs tag -b DRUPAL-6--2

In my case, I used it to go from DRUPAL-6--1 to DRUPAL-7--1 which worked the same way. Note that this checkout remains a DRUPAL-6--1... To switch to the new branch add yet another checkout:

  $ cvs checkout -r DRUPAL-6--2 contributions/modules/foo

(in my case, I used DRUPAL-7--1 instead of DRUPAL-6--2)

What makes it different from the tagging (see below) is the -b option after the tag comment.

CVS tagging

Note: before you start tagging, it is suggested that you create a branch for the development version. Thus, first call something like this:

	cvs tag -b DRUPAL-6--1

Once you are ready to create a 1.0 version, then create the branch. (I suggest you wait for the -dev to appear otherwise the 1.0 will appear before the -dev creating a "conflict" in the Avaialble Updates screen.)

The Drupal website uses CVS. It is old technology, but it is very well integrated with the site. For instance, adding a tag with:

	cvs tag DRUPAL-6--1-0

automatically generates a version of your module with a name set to: <module name>-6.x-1.0.tar.gz.

Creating a patch

In order to create a patch that works with the Drupal site you want to use the Unix utility called diff. That utility compares your current version with a fairly recent version of the file found in the repository.

The command line uses the d, u and r letters ("dur" in French means "hard").

	diff -dur old-file new-file >file.patch

The resulting file is a text file that you can send to another programmer. To apply such a patch you use the patch command or just edit the patch file and see whether you want to apply the changes...

The patch command will add many rather annoying lines whenever a conflict arise. So watch out. I suggest you check in your current version first, apply the patch and if it generates too many conflicts restore your file and apply the changes by hand. I usually ends up being a lot easier.

	cd /path/to/the/file
	patch <file.patch

The patch command line needs to run in the directory where the file to be patched is found. The path defined in the patch file is ignored.

If you use the CVS repositor or have an SVN repository, it is possible to create a patch with those tool and the diff command:

	cd /path/to/the/file
	cvs diff -du file >file.patch
	svn diff file >file.patch

Notice that the SVN diff command already includes the -du flags. If you are creating a patch for the HEAD on Drupal with a module that includes tests, then you'll need to use the CVS from Drupal to get the right path.

Creating the en.pot file

I know how to create a .pot file with Unix commands, I have done it before. But for Drupal, it looks like they have some special handling. Plus, it has to work with PHP, not just any gettext() call. So I looked into how to do that.

Drupal 5.x would use a script named extract.php so something like that (never used D5!) This has been replaced by a new translation module named potx.

Now you're armed with the tool you need to generate your .pot files!

Personately, I use the command line (CLI) version.

  cd module-folder
  php ~/tools/drupal/potx-cli.php

This script generates a file called general.pot that you can then copy in your po folder. Give it the two letter name of the default module language (i.e. if the module is in English, then name it en.pot, if it is French, use fr.pot, etc.)

Note that for Drupal 6+ the translation files are not included in modules anymore. They are expected to be in the translation repository and automatically installed by the Drupal Core system when you install a module.