[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4. User Manual

This chapter provides a step-by-step guide to using Patcher. Everything there is to know about Patcher is here, though the features are introduced progressively.

All user options that are going to be presented in this manual can be found in the patcher customization group, or a subgroup of it.

4.1 Project Descriptors  The project specification mechanism
4.2 Mail Preparation  Customizing Patcher messages
4.3 Patch Generation  Specifying how a patch is to be constructed
4.4 ChangeLogs Handling  How Patcher behaves with respect to ChangeLogs
4.5 Project Check In  Committing your changes from Patcher
4.6 Mail Sending  Sending the message and cleaning up the place
4.7 More On Commands  Error handling and other generalities
4.8 More On Subprojects  Defining permanent subprojects

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1 Project Descriptors

Projects specifications are stored in patcher-projects. This user option is actually a list of project descriptors. Each project descriptor has the following form: `(NAME DIR :OPTION VALUE ...)'

NAME is a string naming your project, DIR is a string specifying the directory in which it resides. The remainder of a project descriptor is a sequence of zero or more option/value pairs, that we call project options. All option names start with a colon. The type of a value depends on the corresponding option. For example, there is a project option named :to-address, whose value should be a string giving the email address to which you want to send Patcher messages.

When Patcher needs the value for a particular project option, it looks for it directly in the project descriptor, but also in other places. This process is described below.

4.1.1 Themes  Collections of options
4.1.2 Project inheritance  Getting options from other projects
4.1.3 Fallbacks  Default values for project options
4.1.4 Retrieval  The process of getting an option's value
4.1.5 Inheritance or theme ?  The proper way to factor out option values

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.1 Themes

If you have several projects sharing the same option set, you might want to setup a theme. Themes are named collections of project options.

Themes are stored in the patcher-themes user option. This option is a list of themes. Each theme has the following form: `(NAME :OPTION VALUE ...)'.

NAME is the theme's name (a symbol). The remainder of the list is a sequence of zero or more option/value pairs, just like in project descriptors.

In order to use a theme in a given project, a :themes project option is provided. It is a list of theme names (symbols). Use this option in your project descriptor, and the project will implicitly inherit all options from the corresponding theme.

One important note: as :themes is a project option, it can appear in a theme. In other words, themes can inherit from other themes. When Patcher tries to retrieve an option, the themes tree is traversed in depth first.

Because themes can contain themes, a bogus setting might lead to an infinite loop (a cycle in a theme graph). To prevent this, the patcher-max-theme-depth user option is provided. It represents the expected maximum theme nesting level, and defaults to 8.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.2 Project inheritance

When two projects are very similar, you might want to use the project inheritance mechanism described below.

There is a special project option called :inheritance. This option must be a list of project names (strings). The inheritance of a project defines a list of projects from which to inherit options.

One important note: inherited projects might have their own :inheritance option set to other projects in turn. In other words, the project inheritance can be more than one level deep. When Patcher tries to retrieve an option, the inheritance tree is traversed in depth first.

Because inherited projects can inherit from projects, a bogus setting might lead to an infinite loop (a cycle in a project graph). To prevent this, the patcher-max-inheritance-depth user option is provided. It represents the expected maximum project inheritance level, and defaults to 8.

The :inheritance project option is somewhat special in the sense that it can't appear in a theme. We will encounter other exceptions later in this manual.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.3 Fallbacks

For each existing project option, Patcher also has a fallback user option with a default value that would be shared among all (or some of) your projects. The name of the fallback is obtained by replacing the colon in the project option's name with the prefix patcher-default-. For example, the fallback corresponding to the :to-address project option is named patcher-default-to-address.

The :inheritance project option is also special in the sense that it doesn't have a corresponding fallback. We will encounter other exceptions later in this manual.

In the remainder of this manual, we will rarely mention the fallbacks again. When we introduce a new project option, just remember that it always has a corresponding fallback (well, not always, as you just discovered).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.4 Retrieval

When Patcher needs the value of a particular project option, it looks for it in the following manner:

Note that a value of nil for a project option is an actual value. It is not equivalent to an option being unset. As a consequence, if Patcher finds a project option with a value of nil somewhere, it will use it and stop the search, even if a non nil value could be retrieved later from a theme, an inherited project or a fallback. This provides you with a way to annihilate themed, inherited or fallbacked options.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.1.5 Inheritance or theme ?

At that point, you might be wondering why the themes and inheritance concepts were both designed, since they actually perform very similar tasks. Good question. Here is a good answer.

Projects might share options for different reasons. For example, my "XEmacs" (source) and "XEmacs Packages" projects share many options (To: address, From: address, diff and commit commands and so on) because they both relate to XEmacs. On the other hand I have personal but totally unrelated projects that share the same commands because they are all handled through a common system: Darcs.

In other words, you should rather use the inheritance mechanism when projects relate to each other, and the theme mechanism for settings that are orthogonal the projects they apply to.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2 Mail Preparation

Patcher currently uses the mail buffers as "master" buffers for controlling all operations: building a patch, creating the ChangeLog entries, committing... all is done from the mail buffer. Note however that you don't need to actually send mails to use Patcher (see section Fake Mail Method).

To use Patcher on a certain project, you start by preparing a (possibly fake) mail. There are several ways to do so: you could start a brand new message, "adapt" a message already in preparation to Patcher, or even compose some sort of a Patcher reply to another message.

Function: patcher-mail
Start composing a brand new Patcher message. This function interactively prompts you for the name of the project and for a (mail) subject line.

Function: patcher-mail-adapt
Assuming that you are already editing a message (with your usual MUA), this function "adapts" it to Patcher by prompting you for the name of a project. Note that this function does not prompt you for a subject.

If you're using Gnus to read mail and have properly insinuated it (see section 2.3 Insinuation), Patcher offers different Gnus-like ways to answer mails and adapt them to Patcher. All the functions below are available from both the Gnus Summary and the Article buffer.

Function: patcher-gnus-summary-followup
Compose a followup to the article, and adapt it to Patcher. This function is bound to C-c C-p f.

Function: patcher-gnus-summary-followup-with-original
Idem, but also cite the original article. This function is bound to C-c C-p F.

Function: patcher-gnus-summary-reply
Like patcher-gnus-summary-followup, but compose a reply. This function is bound to C-c C-p r.

Function: patcher-gnus-summary-reply-with-original
Idem, but also cite the original article. This function is bound to C-c C-p R.

In any case, Patcher starts working on the project (by first creating the patch) after the message is prepared. Because of this, we'll start by reviewing the mail-related customizations you might want to setup.

4.2.1 Mail Methods  Using a particular mailer
4.2.2 Message Customization  Specifying initial contents for messages

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2.1 Mail Methods

Since there are different mail packages working in XEmacs, Patcher supports different methods for preparing messages. You can specify the method you prefer in the :mail-method project option. The value must be a symbol. Standard Mail Methods  Patcher supports standard mail packages Fake Mail Method  Patcher supports not sending mails Other Mail Methods  Patcher supports everything

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Standard Mail Methods

Patcher currently supports `sendmail', `message' and `Gnus' natively and through the `compose-mail' interface. Other MUA might be partly supported when used with compose-mail. Patcher will probably suffer from non critical deficiencies in that case however (it will issue warnings).

This is the default. It is implemented via the function patcher-mail-compose-mail which calls compose-mail to prepare the message. If you are not familiar with `compose-mail', you might also want to throw an eye to the user option mail-user-agent. If your project does not specify an address to send the message to (see section 4.2.2 Message Customization), it is prompted for.

A direct interface to the mail function from the sendmail package. It is implemented via the function patcher-mail-sendmail. If your project does not specify an address to send the message to (see section 4.2.2 Message Customization), it is prompted for.

A direct interface to the message-mail function from the message library (it is part of Gnus). It is implemented via the function patcher-mail-message. If your project does not specify an address to send the message to (see section 4.2.2 Message Customization), it is prompted for.

A direct interface to the gnus-post-news function from the Gnus package (it can also send mails...). It is implemented via the function patcher-mail-gnus. This mail method is interesting when you maintain a special mail group for messages that you send with Patcher, most probably because they are sent to some mailing-list, such as xemacs-patches@xemacs.org.

This method uses a Gnus group name and acts as if you had type `C-u a' on that group in the *Group* buffer, hence honoring the group parameters and posting-styles. If your project does not specify a Gnus group name (see section 4.2.2 Message Customization), it is prompted for.

This last mail method is special in the sense that it requires a running Gnus session to work. If that's needed, Patcher can start Gnus for you in several ways, according to the following user options:

If nil, Patcher will never start Gnus and abort the operation instead. If t, Patcher will always start Gnus when needed. If 'prompt, Patcher will ask you what (you want) to do. This is the default behavior.

Used when Patcher has to start Gnus by itself. If nil, continue using the current frame. If t, start Gnus in another frame (this is the default). If 'follow, start Gnus in another frame, and use this new frame to prepare the Patcher mail.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Fake Mail Method

At that point, you might be wondering why the mail method is a project option and not simply a user option, since you probably only use one mail agent at all. Right. But you might one day work on projects for which you don't need to send messages at all. This could happen if you start using Patcher on a project of your own for instance. For that reason, there is a fake mail method available. It is implemented via the patcher-mail-fake function and calls no particular mail user agent. Once you type `C-c C-c' to virtually send the fake message, it only performs some cleanup.

All right. But did we really need this fake method ? I mean, one could use the usual mail method, and simply not send the message in the end. Huh, yeah, ok... Actually, it is very probable that in a future release of Patcher, the mail buffer won't be the master buffer anymore, and mail sending will be just another optional step in the process. In that case, the mail method is likely to move away from project option to standard user option.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Other Mail Methods

If you're not satisfied with the provided mail methods (want a vm one ?), you can provide your own, more or less. Here's what to do: set your :mail-method project option to, say, foo, and write your own function which must be named patcher-mail-foo.

This function must take two arguments (a project descriptor and a string containing the subject of the message), and prepare a mail buffer. If you want to do this, you should see how it's done for the built-in methods.

Note that the mail adaptation facility won't be available for your custom method. For that, I would have to hack the internals of Patcher.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2.2 Message Customization

When preparing a message, Patcher can fill some parts of it for you. Here's a list of mail-related project options.

The name (your name) to use when composing the message. It will affect the From: header. This option is used by all mail methods but fake. If not given, user-full-name is used.

The mail (your mail) address to use when composing the message. It will affect the From: header. This option is used by all mail methods but fake. If not given, user-mail-address is used.

The address to send messages to (a string). This option is used by all mail methods but gnus and fake. If not given, it is prompted for when calling patcher-mail.

The Gnus group name to use for posting messages (a string). This option is used only by the gnus mail method. If not given, it is prompted for when calling patcher-mail.

Note that if you configured your name and mail in Gnus, for instance through posting styles, these configurations take precedence over the corresponding Patcher options.

A prefix for the subject line of messages. It can be nil or a string. By default, "[PATCH]" is used. This part of subjects is never prompted for. A `%n' occurring in this string will be replaced with the project name. Also, a space is inserted between the prefix and the remainder of the subject, when appropriate.

A default value for prompted subjects (a string). A `%n' occurring in this string will be replaced with the project's name (see section 4.8.2 Subproject Naming). Please note that this is used only to provide a default value for prompted subjects. Subjects are always prompted for.

A prologue to insert just at the top of a message body (a string).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3 Patch Generation

Patcher creates patches by diffing your local copy of the project against the repository. This is done automatically after preparing a message, so you shouldn't normally bother to do it manually. That situation might still happen from time to time, like, if you further modify the sources, or if the initial operation failed for some reason (see section 4.7 More On Commands).

The way to (re)generate the patch manually is to call patcher-generate-diff from the mail buffer. This function is bound to `C-c C-p d' in this buffer. You can both customize the diff command used to (re)generate the patch, and restrict the diff to a subset of the project's files.

When possible, Patcher also tries to check that your project is up-to-date with respect to the archive, and will inform you otherwise.

4.3.1 Diff Command  Specifying the command to generate the patch
4.3.2 After Diff Hook  Tweaking the diff output
4.3.3 Diff Line Filter  Omitting lines from the diff output
4.3.4 Patch Restriction  Specifying the files affected by the patch
4.3.5 Patcher Instances  You can have several instances of Patcher
4.3.6 Diff Prologue  A header is inserted above the patch

By the way, (re)generating the patch does not necessarily mean that it is directly inserted into the mail buffer. This also depends on the ChangeLogs behavior (see section 4.4 ChangeLogs Handling).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3.1 Diff Command

The diff command used to generate the patch is specified by the :diff-command project option. By default, the command used is `cvs -q diff -u'. You can also punctually change this command by calling patcher-mail or patcher-generate-diff with a prefix argument. Patcher will then prompt you for a new command and use it exclusively for this particular patch.

For detail about the format of this option, see 4.3.4 Patch Restriction. See also 4.7 More On Commands.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3.2 After Diff Hook

Sometimes, you might want to tweak a little the diff output before doing anything with it, for instance, before generating ChangeLog skeletons (see section 4.4 ChangeLogs Handling), or simply inserting it into the mail buffer.

In order to do that, you might want to use the :after-diff-hook project option. It should be a list of function names (symbols) that will be called after each diff output. Each function should take two optional arguments delimiting a region to process (no arguments means process the whole buffer) and work in the current buffer. The point is originally placed at the beginning of the region, and the buffer excursion is saved for you.

Note: Patcher provides a special function named patcher-prcs-diff-convert that can be used in this hook in order to convert PRCS diff output to a traditional one.

Note: Patcher provides a special function named patcher-prcs-darcs-convert that can be used in this hook in order to convert Darcs diff output to a traditional one.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3.3 Diff Line Filter

When generating a global diff, that is, without specifying the files affected by the patch explicitly (see section 4.3.4 Patch Restriction), some uninformative lines might be present in the output. A typical example is files present in your local copy but unknown to the CVS server. Such files are indicated by a question mark in diff outputs.

Patcher has a project option named :diff-line-filter that lets filter out such unwanted lines when inserting the diff in the mail buffer. This must be a regular expression matching a whole line. Caution however: do not put beginning or end of lines markers in your regexp. Patcher will do it for you.

By default, the value is "\\? .*", which excludes files unknown to the CVS server.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3.4 Patch Restriction

Sometimes, you don't want to generate a global patch, but instead work on a subset of the project's files. Patcher understands this concept as working on a subproject.

As for working on whole projects, there are several alternatives to start working on a subproject:

Function: patcher-mail-subproject
This function behaves exactly like patcher-mail, except that it also prompts you for the files affected by the patch. You can specify files as well as directories, use wildcards, just as you would construct a command line diff.

Function: patcher-mail-adapt-subproject
Idem, with respect to patcher-mail-adapt.

Finally, all the Gnus-specific reply functions (see section 4.2 Mail Preparation) take an optional prefix argument that make them work on subprojects.

Two important things are to be kept in mind when working on subprojects:

When working on a subproject, Patcher uses the same diff command as the one used for the whole project, that is, the value of the :diff-command project option. In the case of a subproject however, Patcher has to know where to put the files on the command line (even if it's usually the last part of it). This is done with the special construct `%f': a `%f' appearing in the diff command will be replaced with the specified files (and the computed ChangeLog files) for a subproject, and will simply be removed when working on the whole project.

As an example, given that the default diff command used by Patcher is cvs -q diff -u, you should know understand that the default value for patcher-default-diff-command is `cvs -q diff -u %f'. Do you ?

There is another special construct available in this command: a `%n' will be replaced with the project's name (see section 4.8.2 Subproject Naming). This is useful in commands with weird options syntax, like PRCS.

For a more advanced way of handling subprojects, see 4.8 More On Subprojects.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3.5 Patcher Instances

The concept of subprojects brings up the question of having Patcher working on different patches at the same time. It is possible under some conditions:

This last point will be subject to improvements in the future.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.3.6 Diff Prologue

Patcher can (and does) insert a special prologue just above a patch in the message in preparation. This prologue gives information such as the diff command used, the files affected and so on.

The function used to generate this prologue can be specified with the :diff-prologue-function project option. A value of nil means don't insert any prologue. By default, the internal function patcher-default-diff-prologue is used. If you want to provide your own, here how to do it.

Your function should take one argument indicating the kind of diff (a symbol), and perform insertion at current point in the current buffer. The possible values for the argument are:

indicates a source diff only,

indicates a ChangeLog diff only,

indicates a diff on both source and ChangeLog files.

The following variables are bound (when appropriate) when this function is executed:

the name of the current Patcher project,
the command used to create a source diff,
the command used to create a ChangeLog diff,
sources files affected by the current patch,
ChangeLog files affected by the current patch.

In the case of a mixed diff, a nil value for change-log-diff indicates that the same command was used for both the source and ChangeLog files.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.4 ChangeLogs Handling

ChangeLogs management in Patcher involves two aspects: how ChangeLog entries are created, and how they appear in the messages. Both aspects can be customized beyond your craziest dreams.

4.4.1 ChangeLogs Action  How Patcher deals with ChangeLogs
4.4.2 ChangeLogs Appearance  How ChangeLogs appear in messages
4.4.3 ChangeLogs Prologue  A header is inserted above the ChangeLogs

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.4.1 ChangeLogs Action

The way Patcher deals with ChangeLogs is controlled via the :change-logs-updating project option. Its value must be a symbol from the following:

This is the default. Each time you (re)generate a diff, Patcher (re)creates ChangeLog skeletons in the appropriate ChangeLog files, by analyzing the generated diff. You then have to fill the entries manually. Caution: the diff analysis is not done by Patcher directly, but by the function patch-to-change-log from the add-log library from the xemacs-base package. Only standard diff and cvs diff output are currently supported, both in unified format only.

Patcher assumes that you create ChangeLog entries manually, as you write code, so it won't create ChangeLogs skeletons. It is important to understand that in this situation, ChangeLog entries must have been written before you call Patcher. Patcher won't let you write them in the process.

The project doesn't have ChangeLog files. Patcher won't try to create ChangeLog entries, and won't expect that you have written some either.

If you're working in automatic updating mode, Patcher has two other project options that give you some control on the created entries: :change-logs-user-name and :change-logs-user-mail. As you might expect, these are strings defining your name and mail address for ChangeLog entries'headers. When nil, Patcher falls back to (respectively) the :user-name and :user-mail project options. If in turn set to nil, Patcher lets the function patch-to-change-log decide what to use (most probably what the user options user-full-name and user-mail-address say).

Here's a last point to mention about the automatic updating mode. In order to build the ChangeLog skeletons, the source files must be visited. Patcher has a :kill-source-files-after-diffing project option that lets you decide whether you want to kill the source buffers just after diffing or not. The value can be either nil or t. By default, the behavior is to preserve the source files, since you might need them for reference when filling the ChangeLog entries.

If you're working in manual updating mode, Patcher might still need to know the affected ChangeLog files (for the commit process) and your exact ChangeLog entries in each of these files (for insertion in the message). The ChangeLog files are automatically deduced from the patch. When that's required, however, you will be presented with each ChangeLog file in turn, and invited to precise the number of ChangeLog entries concerning this patch. These entries must of course appear at the top of the file.

Finally, note that an updating mode of none is the only case where ChangeLog files are regarded as normal ones if present. As a consequence, that is a case where it is not forbidden to list them explicitly as part of a subproject (see section 4.3.4 Patch Restriction), although I don't see why you would want to do that.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.4.2 ChangeLogs Appearance

When Patcher has to deal with ChangeLog files, you insert ChangeLog entries in the message buffer by calling the function patcher-insert-change-logs. It is bound to `C-c C-p i' in the mail buffer. Note that if ChangeLogs are written in advance, you don't have to do that, as Patcher will do it automatically. You have to call this function by hand only in automatic updating mode (see section 4.4.1 ChangeLogs Action).

In all circumstances however, you can use this function to reinsert the ChangeLog entries into the mail buffer. That might come in handy if you further modified them after the initial insertion (it's never too late to fix a typo).

The appearance of ChangeLog entries in the message is controlled by the :change-logs-appearance project option. Its value must be a symbol from the following:

This is the default. ChangeLog entries appear just as text in the message, above the patch. Most people prefer this kind of appearance since it is the most readable.

ChangeLog entries appear as a patch (they are diff'ed against the archive). This patch is however distinct from the source patch, and appears above it.

ChangeLog entries appear as a patch (they are diff'ed against the archive), and this patch is integrated into the source patch. In other words, the message looks like a global patch integrating both the sources and the ChangeLogs.

When the ChangeLogs appearance is either packed or patch, the diff command used to generate the patch is controlled by the :change-logs-diff-command project option. The value can be the symbol diff, meaning that the same diff command is to be used as for the sources (see section 4.3.1 Diff Command), or it can be a string specifying an alternate command.

When diffing ChangeLog files, it is strongly recommended that you remove contexts from the diff, because otherwise, ChangeLog patches often fail to apply correctly.

As in the case of the :diff-command project option (see section 4.3.4 Patch Restriction), a %f serves to indicate where to put the ChangeLog files on the diff command line, and a `%n' is replaced with the project's name (see section 4.8.2 Subproject Naming). See also 4.7 More On Commands.

Given these two remarks, you should now understand why the default value for patcher-default-change-logs-diff-command is `cvs -q diff -U 0 %f'.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.4.3 ChangeLogs Prologue

ChangeLog prologues are small pieces of informative text that Patcher adds above each ChangeLog insertion in the mail buffer.

When the ChangeLogs appearance is verbatim, Patcher inserts one prologue per ChangeLog file. The prologue's contents is controlled by the :change-logs-prologue project option (a string). A `%f' appearing in this string will be replaced with the ChangeLog filename. The default value for patcher-default-change-logs-prologue is "%f addition:".

When the ChangeLogs appearance is packed, Patcher inserts only one prologue for the whole ChangeLogs patch. When patch, there is a single prologue for both the ChangeLogs and the sources. For customizing the prologue in both of these cases, see 4.3.6 Diff Prologue.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.5 Project Check In

If you have the privilege to commit your changes yourself, you might do so directly from the mail buffer, as the last operation before actually sending the message. This is done by calling the function patcher-commit-change which is bound to `C-c C-p c' in the mail buffer.

Committing directly from Patcher has the advantage that both the commit command line and the commit log message (see section 4.5.2 Log Message Handling) are constructed automatically. Of course, you still have an in-depth control on the commit process.

4.5.1 Commit Command  Specifying the command to commit the patch
4.5.2 Log Message Handling  Building a commit log message
4.5.3 Commit Operation  Actually committing your changes

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.5.1 Commit Command

The command used to to commit a patch is specified by the :commit-command project option (a string). You can also temporarily change the command in question by calling patcher-commit-change with a prefix argument. As usual, note that this prefix argument is not meant to modify the affected files on the command line. It's meant only to punctually modify the commit command itself. The affected files are computed automatically by Patcher.

The commit command accepts (and maybe requires) special constructs:

Please note that a %f is required in your commit commands, unless you know for sure that you will never ever work on a subproject (see section 4.3.4 Patch Restriction). But you never know that. Besides, you should always also provide either a %s or a %S, unless your archival software does not support log messages.

Given that, you should now understand why the default value for patcher-default-commit-command is `cvs commit -F %s %f'.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.5.2 Log Message Handling

Most project management tools understand the concept of a log message: a short yet informative message that accompany the commit operation, which is also stored in the repository.

Before a commit operation, Patcher always builds an initial log message, based on certain elements under your control (see section Log Message Elements). Afterwards, you can decide on whether you want some further (manual) edition of log message, or whether you want to commit immediately.

The :edit-log-message project option lets you specify this behavior. If t (the default), you will be able to manually edit the log message. If nil, Patcher will proceed directly to the commit operation.

Please note that Patcher stores log messages in temporary files that will be used later by the commit command. Log Message Elements  Elements Patcher can add automatically Log Message Editing  Manually modifying the log message

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Log Message Elements

Patcher has the ability to initialize the log message with different elements. These elements are specified with the :log-message-items project option. Its value is either nil, meaning that you don't want any initialization, or a list of symbols specifying the elements you desire. The available items are:

The subject of the message. The subject's prefix is automatically removed.

The "compressed" ChangeLog entries. Only the most important part of the ChangeLogs is preserved, so the entries appear in a more compact fashion.

The raw ChangeLog entries.

By default, only the message's subject is used. When using more than one item, they appear in the order specified above. If anything appears before the raw ChangeLog entries, a separator string is used. This string is specified by the :change-logs-separator project option. By default the string looks like "--- ChangeLog entries follow: ---".

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Log Message Editing

If so required, Patcher lets you manually edit the log message after having initialized it. Log message edition happens in a special buffer, the *Patcher Log Message* buffer.

While editing this buffer, commands to insert the items described in Log Message Elements are at your disposal. These commands perform insertion at point:

Bound to `C-c C-p s'. Insert the message's subject (sans the prefix).

Bound to `C-c C-p c'. Insert the compressed ChangeLog entries.

Bound to `C-c C-p l'. Insert the raw ChangeLog entries. Use a prefix argument if you also want the ChangeLogs separator string to be inserted.

In addition to these commands, you can also completely reinitialize the log message according to the specified items, by calling the function patcher-logmsg-init-message, bound to `C-c C-p i'. Caution: this command first erases the buffer.

Finally, once you're happy with your log message, you proceed to the commit operation by calling the function patcher-logmsg-commit, bound to `C-c C-c'.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.5.3 Commit Operation

The commit operation occurs after typing `C-c C-p c' from the mail buffer, if you have not required log message edition, or after typing `C-c C-c' from the *Patcher Log Message* buffer otherwise.

At that point, Patcher has constructed a proper commit command. You still have an option to abort the process, though: the :confirm-commits project option lets you specify whether to require confirmation before committing. If t (the default), Patcher will display the constructed commit command and ask for a confirmation before proceeding. If nil, Patcher will commit immediately.

After the commit operation, Patcher changes some parts of the mail buffer in the following manner:

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.6 Mail Sending

Sending the message will most probably be done by typing `C-c C-c' in the mail buffer. This is also the case when you're using the fake mail method, by the way.

4.6.1 Before Sending  Patcher does some checkings
4.6.2 After Sending  patcher does some cleanup

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.6.1 Before Sending

There are circumstances in which Patcher will perform some checkings on your message when you send it, just before it is actually sent:

Two notes on these checkings:

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.6.2 After Sending

After sending the message, Patcher also performs some cleanup operations, that you can customize. The cleanup is controlled by the following project options. Each one is a boolean option which defaults to t.

Whether to kill source files after sending the message. If nil, the source files will remain visited.

Whether to kill ChangeLog files after sending the message. If nil, the ChangeLog files will remain visited.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.7 More On Commands

This section deals with information that apply to all commands used by Patcher (diff and commit operations).

4.7.1 Prefixing Commands  Bypassing a firewall
4.7.2 Error Handling  Dealing with errors

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.7.1 Prefixing Commands

If you're working on a distant archive and you're behind a firewall, you might need to prefix all your commands with something like runsocks. Of course, this can be done manually in all your command settings, but Patcher offers you a simpler way to do it.

There is a project option named :pre-command which can be used for this kind of thing. It must be a string that will be prepended to all operations performed by Patcher.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.7.2 Error Handling

From time to time, commands may fail for different reasons. Patcher tracks the failures in these commands and lets you know when that happens. The :failed-command-regexp project option lets you specify a regular expression to match with the output of an aborted command. By default, the value is "^cvs \\[[^]]* aborted\\]".

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.8 More On Subprojects

We've already seen how to work punctually on a subproject, that is, on a subset of a project's files (see section 4.3.4 Patch Restriction). If you happen to work more than once on the same project subset, it will quickly become annoying to have to specify explicitly the same files over and over again. Patcher offers you a way to permanently define subprojects.

4.8.1 Defining Subprojects  Storing subprojects definitions
4.8.2 Subproject Naming  When different projects have the same name
4.8.3 Command Directory  For non local revision control systems

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.8.1 Defining Subprojects

The user option patcher-subprojects stores a list of subproject descriptors. A subproject descriptor is almost the same as a project descriptor, with a few exceptions:

Here are some important remarks about subprojects:

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.8.2 Subproject Naming

As you already know, Patcher distinguishes projects by their NAME field in the patcher-projects and patcher-subprojects user options. This is problematic, however, if you define different patcher projects for a single physical project, and the commands require the project's name. That might for instance be the case with PRCS (decidedly) weird options syntax.

To remedy this problem, patcher provides a :name project option. If set, it will actually be used for all %n substitutions where the project's name (in the Patcher sense) would normally be used.

If you want to use the project's name in the Patcher sense, regardless of the value of the :name option, use %N instead of %n.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.8.3 Command Directory

Some revision control systems, like CVS, work on a per-file basis. Some others, like PRCS, work only globally. This has an important implication for subprojects being sudirectories of other projects. Indeed, while CVS, for instance, can be executed anywhere, PRCS can only be run in the base project's root directory.

If you want to define projects for which the revision control system can be executed in only one directory, Patcher provides you with the :command-directory project option (a string). This directory can be specified relative to the project's directory (but note that it must go upwards).

All commands (diff and commit ones) will be executed from there. Also, note that the command directory does not change the way you might specify files. Patcher modifies all needed paths automatically to handle the command directory properly.

[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by XEmacs Webmaster on October, 2 2007 using texi2html