@need 3200

@node Introducing Changesets
@chapter Introducing Changesets

@geindex applying a patch



It is often extremely useful to compare two project trees (usually for
the same project) and figure out exactly what has changed between
them.  A record of such changes is called a @geindex changeset
@dfn{changeset} or a @geindex delta
@dfn{delta}.


Changesets are a very central concept to @code{arch} -- much of @code{arch} is
defined in terms of operations performed with changesets.


If you have a changeset between an "old tree" and a "new tree",
you can "apply the changeset" to the old tree to get the new tree --
in other words, you can automatically make the editing changes
described by a changeset.  If you have some third tree, you can apply
the patch to get an approximation of making the same changes to that
third tree.


@code{arch} includes sophisticated tools for creating and applying
changesets.

@menu
* mkpatch::
* dopatch::
* Inexact Patching -- How Conflicts are Handled::
@end menu

@need 3200

@node mkpatch
@section mkpatch

@geindex mkpatch

@geindex changeset



@code{mkpatch} computes a changeset describing the differences between two
trees.  The basic command syntax is:

@example
@group
        % larch mkpatch ORIGINAL MODIFIED DESTINATION
@end group
@group
@end group
@end example

@noindent
which compares the trees @code{ORIGINAL} and @code{MODIFIED}.  


@code{mkpatch} creates a new directory, @code{DESTINATION}, and stores the
changeset there.


When @code{mkpatch} compares trees, it uses inventory tags.  For example,
it considers two directories or two files to be "the same directory
(or file)" if they have the same tag -- regardless of where each is
located in its respective tree.  (See @ref{Inventory Tags for Source}.)


A changeset produced by @code{mkpatch} describes what files and directories
have been added or removed, which have been renamed, which files have
been changed (and how they have been changed), and what file
permissions have changed (and how).  When regular text files are
compared, @code{mkpatch} produces a context diff describing the
differences.  @code{mkpatch} can compare binary files (saving complete
copies of the old and new versions if they differ) and symbolic links
(saving the old and new link targets, if they differ).


A detailed description of the format of a changeset is provided in an
appendix (see @ref{The arch Changeset Format}).




@need 3200

@node dopatch
@section dopatch

@geindex dopatch



@code{dopatch} is used to apply a changeset to tree:

@example
@group
        % larch dopatch PATCH-SET TREE
@end group
@group
@end group
@end example

If @code{tree} is exactly the same as the the "original" tree seen by
@code{mkpatch}, then the effect is to modify @code{tree} so that it is exactly
the same as the the "modified" tree seen by @code{mkpatch}, with one
exception (explained below).


"Exactly the same" means that the directory structure is the same,
symbolic link targets are the same, the contents of regular files are
the same, and file permissions are the same.  Modification times,
files with multiple (hard) links, and file ownership are not reliably
preserved.


The exception to the "exactly the same" rule is that if the patch
requires that files or directories be removed from @code{tree}, those files
and directories will be saved in a subdirectory of @code{tree} with an
eye-splitting name matching the pattern:

@example
@group
        ++removed-by-dopatch-PATCH--DATE
@end group
@group
@end group
@end example

@noindent
where @code{PATCH} is the name of the patch-set directory and @code{DATE} a
timestamp. 




@need 3200

@node Inexact Patching -- How Conflicts are Handled
@section Inexact Patching -- How Conflicts are Handled

@geindex inexact patching

@geindex patching (inexact)



What if a tree patched by @code{dopatch} is not exactly the same as the
original tree seen by @code{mkpatch}?


Below is a brief description of what to expect.  Complete
documentation of the @code{dopatch} process is included with the source
code.


@code{dopatch} takes an inventory of the tree being patched.  It uses
inventory tags to decide which files and directories expected by the
changeset are present or missing from the tree, and to figure out
where each file and directory is located in the tree.


@strong{Simple Patches} If the changeset contains an ordinary patch or
metadata patch for a link, directory or file, and that file is present
in the tree, @code{dopatch} applies the patch in the ordinary way.  If the
patch applies cleanly, the modified file, link, or directory is left
in place.


If a simple patch fails to apply cleanly, @code{dopatch} will always leave
behind a @code{.orig} file (the file originally in the tree being patched,
without any changes) and a @code{.rej} file (the part of the patch that
could not be applied).  


If the patch was a context diff, @code{dopatch} will also leave behind the
file itself -- partially patched.


If an (unsuccessful) patch was for a binary file, no partially-patched
file will be left.  Instead, there will be:

@example
@group
        .orig   -- the file originally in the tree being patched,
                   without modifications.
@end group
@group

@end group
@group
        .rej    -- a complete copy of the file from the modified tree,
                   with permissions copied from `.orig'.
@end group
@group

@end group
@group
        .patch-orig -- a complete copy of the file from the original
                       tree seen by `mkpatch', with permissions
                       retained from that original
@end group
@group

@end group
@group
                        -or-
@end group
@group

@end group
@group
                       the symbolic link from the original tree seen
                       by `mkpatch' with permissions as in the original
                       tree.
@end group
@group


@end group
@end example

If an (unsuccessful) patch was for a symbolic link, no partially
patched file will be left.  Instead there will be:

@example
@group
        .orig   -- the unmodified file from the original tree
@end group
@group

@end group
@group
        .rej    -- a symbolic link with the target intended by the
                   patch and permissions copied from .orig
@end group
@group

@end group
@group
        .patch-orig -- a complete copy of the file from the original
                       tree seen by `mkpatch', with permissions 
                       retained from that original
@end group
@group

@end group
@group
                        -or-
@end group
@group

@end group
@group
                       the symbolic link from the original tree seen
                       by `mkpatch' with permissions as in the original
                       tree.
@end group
@group


@end group
@end example

@strong{Patches for Missing Files}


All patches for missing files and directories are stored in a
subdirectory of the root of the tree being patched called 

@example
@group
        ==missing-file-patches-PATCH-DATE
@end group
@group
@end group
@end example

@noindent
where @code{PATCH} is the basename of the changeset directory and @code{DATE} a
time-stamp.


@strong{Directory Rearrangements and New Directories}


Directories are added, deleted, and rearranged much as you would
expect, even if you don't know it's what you'd expect.


Suppose that when @code{mkpatch} was called the @code{ORIGINAL} tree had:

@example
@group
        Directory or file:              Tag:
@end group
@group

@end group
@group
        a/x.c                           tag_1
        a/bar.c                         tag_2
@end group
@group

@end group
@end example

@noindent
but the @code{MODIFIED} tree had:

@example
@group
        a/x.c                           tag_1
        a/y.c                           tag_2
@end group
@group
@end group
@end example

@noindent
with changes to both files.  The patch will want to rename the file
with tag @code{tag_2} to @code{y.c}, and change the contents of the files with
tags @code{tag_1} and @code{tag_2}.


Suppose, for example, that you have a tree with:

@example
@group
        a/foo.c                         tag_1
        a/zip.c                         tag_2
@end group
@group
@end group
@end example

@noindent
and the you apply the patch to that tree.  After the patch, you'll be
left with:

@example
@group
        a/foo.c                         tag_1
        a/y.c (was zip.c)               tag_2
@end group
@group
@end group
@end example

@noindent
with patches made to the contents of both files.


Here's a sample of some subtleties and ways of handling conflicts:


Suppose that the original tree seen by mkpatch has:

@example
@group
        Directory or file:              Tag:
@end group
@group

@end group
@group
        ./a                             tag_a
        ./a/b                           tag_b
        ./a/b/c                         tag_c
@end group
@group

@end group
@end example

@noindent
and that the modified directory has:

@example
@group
        ./a                             tag_a
        ./a/c                           tag_c
        ./a/c/b                         tag_b
@end group
@group
@end group
@end example

Finally, suppose that the tree has:

@example
@group
        ./x                             tag_a
        ./x/b                           tag_b
        ./x/c                           tag_new_directory
        ./x/c/b                         tag_different_file_named_b
        ./x/c/q                         tag_c
@end group
@group
@end group
@end example

When patch gets done with the tree, it will have:

@example
@group
        ./x                             tag_a
                Since the patch doesn't do anything 
                to change the directory with tag_a.
@end group
@group

@end group
@group
        ./x/c.orig                      tag_new_directory
        ./x/c.rej                       tag_c
                Since the patch wants to make the 
                directory with tag_c a subdirectory named "c"
                of the directory with tag_a, but the tree
                already had a different directory there,
                with the tag tag_new_directory.
@end group
@group

@end group
@group
        ./x/c.rej/b                     tag_b
                Since the patch wants to rename the directory
                with tag_b to be a subdirectory named "b"
                of the directory with tag_c.
@end group
@group

@end group
@group
        ./x/c.orig/b                    tag_different_file_named_b
                Since the patch made new changes to this file,
                it stayed with its parent directory.
@end group
@group
                
@end group
@end example






