#LyX 1.3 created this file. For more info see http://www.lyx.org/ \lyxformat 221 \textclass report \language english \inputencoding auto \fontscheme default \graphics default \paperfontsize 12 \spacing single \papersize Default \paperpackage a4 \use_geometry 1 \use_amsmath 0 \use_natbib 0 \use_numerical_citations 0 \paperorientation portrait \leftmargin 1in \topmargin 1in \rightmargin 1in \bottommargin 1in \secnumdepth 3 \tocdepth 3 \paragraph_separation indent \defskip medskip \quotes_language english \quotes_times 2 \papercolumns 1 \papersides 1 \paperpagestyle default \layout Title ArX \layout Standard This document is Copyright (C) 2003-2005 Walter Landry, Copyright (C) 2003 Miles Bader. \newline \layout Standard This work is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 dated June, 1991. \newline \layout Standard This work is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. \newline \layout Standard You should have received a copy of the GNU General Public License along with this work; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \layout Chapter* Credits \layout Standard ArX has been cooperatively developed, and has contributions from many people and organizations. A hopefully complete list: Pau Aliagas, David Allouche, Tim Barbour, Stig Brautaset, Jon Buller, Junio C Hamano, Environment Canada - Meteorological Service of Canada, Mike Coleman, Robert Collins, Don Dayley, Alexander Deruwe, Federico Di Gregorio, Nicholas Dille, Paul Eggert, John Ellson, Robin Farine, Lele Gaifax, Karel Gardas, Johnathan Geisler, Jonathan Geisler, Chris Gray, Jan Harkes, Isamu Hasegawa, Joey Hess, Mikael Hillerstrom, David Kantowitz, Walter Landry, Tom Lord, Andrew Morton, Frank Murphy, Steve Murphy, Gergely Nagy, Matthias Neeracher, Daniele Nicolodi, Scott Parish, Chris Paulson-Ellis, Ulrich Pfeifer, Marc Recht, The Regents of the University of California, Kevin Smith, Richard Stallman, Bruce Stephens, Robert W. Anderson, Bryan W. Headley, Martin Waitz, Colin Walters. \layout Standard In addition, ArX makes use of some wonderful tools from the FSF (www.gnu.org) and four excellent libraries: Boost (www.boost.org), Loki (http://sourceforge.net/ projects/loki-lib/), Brian Gladman's SHA implementation, and Graydon Hoare's xdelta implementation. The code in those libraries requires the following acknowledgements: \layout LyX-Code /* Copyright (c) 2000-2002 \layout LyX-Code * CrystalClear Software, Inc. \layout LyX-Code * \layout LyX-Code * Permission to use, copy, modify, distribute and sell this software \layout LyX-Code * and its documentation for any purpose is hereby granted without fee, \layout LyX-Code * provided that the above copyright notice appear in all copies and \layout LyX-Code * that both that copyright notice and this permission notice appear \layout LyX-Code * in supporting documentation. CrystalClear Software makes no \layout LyX-Code * representations about the suitability of this software for any \layout LyX-Code * purpose. It is provided "as is" without express or implied warranty. */ \layout LyX-Code \layout LyX-Code * Copyright (c) 1998-2002 \layout LyX-Code * Dr John Maddock \layout LyX-Code * \layout LyX-Code * Permission to use, copy, modify, distribute and sell this software \layout LyX-Code * and its documentation for any purpose is hereby granted without fee, \layout LyX-Code * provided that the above copyright notice appear in all copies and \layout LyX-Code * that both that copyright notice and this permission notice appear \layout LyX-Code * in supporting documentation. Dr John Maddock makes no representations \layout LyX-Code * about the suitability of this software for any purpose. \layout LyX-Code * It is provided "as is" without express or implied warranty. \layout LyX-Code \layout LyX-Code // The Loki Library \layout LyX-Code // Copyright (c) 2001 by Andrei Alexandrescu \layout LyX-Code // This code accompanies the book: \layout LyX-Code // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design \layout LyX-Code // Patterns Applied". Copyright (c) 2001. Addison-Wesley. \layout LyX-Code // Permission to use, copy, modify, distribute and sell this software for any \layout LyX-Code // purpose is hereby granted without fee, provided that the above copyright \layout LyX-Code // notice appear in all copies and that both that copyright notice and this \layout LyX-Code // permission notice appear in supporting documentation. \layout LyX-Code // The author or Addison-Wesley Longman make no representations about the \layout LyX-Code // suitability of this software for any purpose. It is provided "as is" \layout LyX-Code // without express or implied warranty. \layout LyX-Code \layout Standard \begin_inset LatexCommand \tableofcontents{} \end_inset \layout Chapter Introduction \layout Standard ArX is a version control system that enables you to do many things that seem difficult or painful with current systems. Suppose you are creating something, be it a program, a document, or even graphics. As you make modifications to the work, you can save the different revisions into an archive as you go along. Then, if you decide that something you deleted is still useful, you can get that old work back. Sometimes it is just the difference between two revisions that is interesting. ArX also makes it easy to get just those differences. \layout Standard As the work becomes larger and more complicated, it spreads into different files. Sometimes you make a number of related changes to a number of files, and you want all of these changes to be committed at the same time. In particular, some of these changes may depend upon each other. ArX supports whole-tree commits, which ensure that all of those changes are grouped together. \layout Standard As the project matures, the logical structure changes, so you move files and directories around. You find it convenient to use symlinks and permissions. ArX stores all of that information, allowing you to get back exactly what you put in. Sometimes, you start working on a change that you may not be completely sure whether it will end up in the final creation. ArX makes it easy to create a branch of your creation that lives in parallel with the main line of development. Once the work on that branch is done, ArX makes it easy to integrate those changes back into the main line of development. Or you can just continue to work on the branch and completely forget about the \begin_inset Quotes eld \end_inset main \begin_inset Quotes erd \end_inset line. \layout Standard Finally, you want to release your work upon the world. ArX supports ways to package up your creation into simple tarballs. People admire your work, and want to help out. This is where ArX's strengths really shine. You can publish your archive so that other people can watch your development, trying out new elements as you create them. You can use a variety of ordinary servers, including an ordinary web server, a web server with webDAV, an ftp server, or an sftp server for secure access. You can also digitally sign the archive to reduce the risk of someone compromis ing the code and inserted hidden bugs. \layout Standard As time goes on, some of the testers become developers, sending in small patches to improve this or that part. They can work in isolation, creating patches that they send to you. You continue to work, and ArX makes it easy for independent developers to keep their tree up to date. They, too, can publish an archive, and ArX makes it easy to integrate patches from them. You can either take everything that they do, or you can selectively apply patches from among the ones they offer. As before, you can easily create branches to try out patches from many different sources, and only integrate those that pan out. \layout Standard In time, you may tire of your creation, and some of your contributors may become more prolific than yourself. ArX makes it easy for anyone to mirror your archive, and anyone can create their own branches. Anyone can become a new maintainer. A new person, or a new group, may come to hold sway over the future of the creation. Their own archives will become the centers of eagerly awaited patches, while your own fades into history. \layout Chapter Installation and Versioning \layout Section Building ArX \layout Standard To build the code you will need a decent C++ compiler. A recent version of gcc (>=3.2) is recommended. The code uses autoconf, so a minimal shell is needed. In addition, you must have Python >=2 (just used for building) and a working gnome-vfs2 install. Finally, ArX uses GNU diff, patch and tar. On Windows, you can get these with Cygwin. See INSTALL.CYGWIN for more details. On Mac OS X, you can use either pkgsrc \begin_inset Foot collapsed true \layout Standard http://www.netbsd.org/Documentation/software/packages.html \end_inset or Fink \begin_inset Foot collapsed true \layout Standard http://fink.sourceforge.net \end_inset . Detailed installation instructions can be found in INSTALL.GENERIC. \layout Standard Once you have it installed and in your path, you can invoke it \layout LyX-Code $ arx \layout Standard and it will give some output \layout LyX-Code Invoke a sub-command of arx. \layout LyX-Code usage: arx command [options] [arguments] \layout LyX-Code \layout LyX-Code All commands take the following options: \layout LyX-Code -h -H --help print a help message specific to that command \layout LyX-Code --silent no output \layout LyX-Code --quiet only output errors \layout LyX-Code --default-output default output \layout LyX-Code --report slightly verbose output \layout LyX-Code --verbose maximal output \layout LyX-Code -- mark the end of options \layout LyX-Code \layout LyX-Code The -- option is useful for explicitly ending the list of options. This \layout LyX-Code is useful if a filename, for example, might be mistaken for an option. \layout LyX-Code \layout LyX-Code In addition, you can specify the following options instead of a command. \layout LyX-Code \layout LyX-Code -V --version print version info \layout LyX-Code -h --help display this help \layout LyX-Code -H --help-commands display a list of subcommands \layout Standard In general, to invoke an ArX command, you type \family typewriter arx \family default followed by the command, then followed by any options, and finally any arguments to the command. \layout Section Versioning \layout Standard You can find out what version of ArX you are running with the \family typewriter -V \family default option: \layout LyX-Code $ arx -V \layout LyX-Code ArX 2.2.2 \layout LyX-Code Built 00:25:42 Apr 28 2005 with gpg support \layout LyX-Code \layout LyX-Code Copyright 2001-2005 by various contributors. See CREDITS for details. \layout LyX-Code \layout LyX-Code This is free software; see the source for copying conditions. \layout LyX-Code There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A \layout LyX-Code PARTICULAR PURPOSE. \layout LyX-Code \layout LyX-Code Report bugs to . \layout Standard The version has three parts, a major, minor, and revision number. Two versions that differ only in revision number (e.g. 2.0.12 and 2.0.15) should be mostly compatible. Commands may be added, modified, or removed, but the disk format will be the same. A minor version change means that the format for anything except an archive may have changed. For example, you may have to delete and re-get a project tree. A major version change means that the archive format has changed, perhaps requiring you to convert archives. \layout Chapter Setup \layout Section IDs \layout Standard The first thing you should do is come up with an ID for yourself. ArX uses it to identify who committed a change to an archive, and who is holding locks on an archive. You can use your name or a pseudonym, as in \layout LyX-Code $ arx param id \begin_inset Quotes eld \end_inset Don Quixote de la Mancha \begin_inset Quotes erd \end_inset \layout Standard The argument is quoted because there are spaces in the name. To see what your ID is, you can use \family typewriter param id \family default without arguments \layout LyX-Code $ arx param id \layout LyX-Code Don Quixote de la Mancha \layout Section Archives \layout Standard Now you need a place to store all of the revisions you are going to be making. This is called an \emph on archive \emph default , and you create one with the \family typewriter make-archive \family default command. You need to know two things before you create the archive: what to call it and where it will be. You can name an archive whatever you like, as long as it does not have a slash \begin_inset Quotes eld \end_inset / \begin_inset Quotes erd \end_inset or colon \begin_inset Quotes eld \end_inset : \begin_inset Quotes erd \end_inset inside it. The usual choice follows a syntax that looks like an email address followed by a further delineation. For example \layout LyX-Code dcoyote@example.org--archive \layout Standard The advantage of using an email address is that it is already unique, so you won't have clashes with another person. You will probably find yourself creating different archives for different purposes, so it is wise to put some sort of qualifier at the end of the name of the archive. For example, if you want to have an archive for your work at Yoyodyne Inc. and another for your spare time, you might choose archive names such as \layout LyX-Code dcoyote@example.org--yoyodyne \layout LyX-Code dcoyote@example.org--freetime \layout Standard Now that you have a name for your archive, you need a place to put it. Any spare directory with a fair amount of space will do. If you have decided to put the archive in the directory \family typewriter archive \family default , then you make the archive with \family typewriter make-archive \layout LyX-Code $ arx make-archive dcoyote@example.org--archive archive \layout Standard Note that you should \series bold never \series default have to look inside that \family typewriter archive \family default directory. \layout Standard The last thing that you should do is set up a default archive. You just use the symbolic name of the archive \layout LyX-Code $ arx param default-archive dcoyote@foobar.org--archive \layout Standard You are now set up for basic revision control. \layout Chapter Basic Revision Control \layout Section \begin_inset LatexCommand \label{sec:The-First-Revision} \end_inset The First Revision \layout Standard ArX works on entire project trees, so everything has to be stored within a directory. This differs from some simpler revision control systems such as RCS which can operate on just one file. So we need to create a directory to store our files. We will illustrate with the simplest shell script, Hello world. We create the directory \layout LyX-Code $ mkdir hello \layout Standard and then create the program \layout LyX-Code $ cd hello \layout LyX-Code $ echo "echo Hello, World" > Hello \layout Standard Now we are going to store this masterpiece in ArX. We first have to initialize the tree, letting ArX know that we are creating a new project. We will call the project "hello". \layout LyX-Code $ arx init hello \layout Standard This creates an \family typewriter _arx \family default sub-directory in the current directory. You should never need to look at things in the \family typewriter _arx \family default directory. It also automatically recursively adds all of the paths (files and directories) in the directory to the list of paths that will get stored in the archive. \layout Standard You can now store the first revision in your archive by running \layout LyX-Code $ arx commit -s \begin_inset Quotes eld \end_inset First revision \begin_inset Quotes erd \end_inset \layout Standard If later you decide that you want to get back this initial revision, you use \family typewriter get \layout LyX-Code $ arx get hello,0 \layout Standard This is the initial revision, so it has \family typewriter \begin_inset Quotes eld \end_inset ,0 \begin_inset Quotes erd \end_inset \family default appended to the end of the revision. Later revisions will have \family typewriter \begin_inset Quotes eld \end_inset ,1 \family default \begin_inset Quotes erd \end_inset , \family typewriter \begin_inset Quotes eld \end_inset ,2 \family default \begin_inset Quotes erd \end_inset , etc. appended. \layout Section Further Revisions \layout Standard Now suppose that you have made some modifications to your project. Commiting the changes is just \layout LyX-Code $ arx commit -s \begin_inset Quotes eld \end_inset Fixed foo to do bar instead of baz \begin_inset Quotes erd \end_inset \layout Standard You can continue this simple scheme ad infinitum as long as you don't need to add, delete, or move files. \layout Section More complicated changes \layout Standard Sooner rather than later, you will want to add more files. ArX requires you to explicitly notify ArX every time you add a file. You do this with the \family typewriter add \family default command. For example, if you created a file named \begin_inset Quotes eld \end_inset Goodbye \begin_inset Quotes erd \end_inset , you can add it by typing \layout LyX-Code $ arx add Goodbye \layout Standard This works on directories as well, although not recursively by default. If you do not explicitly add a file, then ArX will not store it or any modifications into the archive. If you do not add a directory, any changes that occur in that directory will not be recorded. \layout Standard Similarly, if you later decide that you don't need \begin_inset Quotes eld \end_inset Goodbye \begin_inset Quotes erd \end_inset anymore, you can delete it with the command \layout LyX-Code $ arx rm Goodbye \layout Standard \family typewriter arx rm \family default supports most of the same semantics as rm(1), so you can recursively and interactively delete files and directories. Finally, you can move files \layout LyX-Code $ arx mv Goodbye Goodbye.sh \layout Standard \family typewriter arx mv \family default supports most of the semantics of plain old mv(1), so you can move a number of files into a subdirectory \layout LyX-Code $ arx mv foo bar baz bat/ \layout Standard If you forget to use the ArX functions to delete and move files and directories, ArX will not let you commit. You can use the \family typewriter tree-lint \family default to see what kinds of problems might arise during commit. \layout LyX-Code $ arx tree-lint \layout Standard Some of the things that \family typewriter tree-lint \family default complains about are only warnings that will not stop a commit. For example, if you forget to \family typewriter add \family default a file. In general, if you have been doing a lot of modifications to the tree, it is wise to run \family typewriter tree-lint \family default before committing. \layout Standard If you have made so many changes over such a long time that you have forgotten exactly what you have done, \family typewriter then \layout LyX-Code $ arx diff \layout Standard will tell you what paths have changed since the last time you committed. \layout Section Reviewing your work \layout Standard You can get a terse listing of the revisions you have committed with \layout LyX-Code arx log \layout Standard Alternately, \layout LyX-Code arx log --formatted \layout Standard will give a more detailed picture. These commands look in the project tree for the information. If you are not in the project tree, then \layout LyX-Code arx log --remote \layout Standard will instead query the archive. Given this listing of revisions, you can get a particular revision (e.g. revision 12) with \layout LyX-Code arx get hello,12 \layout Standard This puts revision 12 into the directory \family typewriter hello.12 \family default . Note that this is different from CVS, because you didn't have to explicitly tag a revision in order to get a particular snapshot of the tree. Every revision is akin to a snapshot. \layout Section Working with an existing project \layout Standard Suppose your trusty sidekick Sancho Panza has set up an archive at \layout LyX-Code ftp://ftp.example.org/~spanza/archive/ \layout Standard You can register that archive with the archives command \layout LyX-Code arx archives -a ftp://ftp.example.org/~spanza/archive/ \layout Standard ArX will retrieve the name of the archive from the archive itself. If Sancho Panza named the archive \family typewriter spanza@example.org \family default when he created it, then running \family typewriter archives \family default without arguments should give you output like \layout LyX-Code $ arx archives \layout LyX-Code \family typewriter spanza@example.org \layout LyX-Code ftp://ftp.example.org/~spanza/archive \layout Standard However, you don't need to explicitly register the archive. ArX will do it for you whenever you access the archive (e.g. when using \family typewriter browse \family default or \family typewriter get \family default ). So to see what is there, you can run \layout LyX-Code arx browse ftp://ftp.example.org/~spanza/archive/ \layout Standard The trailing slash \begin_inset Quotes eld \end_inset / \begin_inset Quotes erd \end_inset is important. ArX assumes that everything past the last slash is a branch name, so without the trailing slash ArX would be looking for the archive branch in an archive located at ftp://ftp.example.org/~spanza/. \layout Standard Now that the archive is registered, you can use the archive name instead of URL's. For example, to get the windmill project from that archive, you can use \layout LyX-Code arx get spanza@example.org/windmill windmill \layout Standard But using the full URL will always work \layout LyX-Code arx get ftp://ftp.example.org/~spanza/archive/windmill windmill \layout Standard Once you have this project, you can keep up to date with any changes to the project with \layout LyX-Code arx merge --dir windmill \layout Standard The \family typewriter merge \family default command is analogous to the update command in CVS, although \family typewriter merge \family default is much more powerful. You can set up ArX to pop up a graphical merge tool in case of conflicts. See Appendix \begin_inset LatexCommand \ref{cha:Sample-Merge-Scripts} \end_inset for details. \layout Chapter Advanced ArX Concepts \layout Standard The preceding chapters gave a basic introduction to working with ArX. However, some of the things that make ArX so useful necessarily become somewhat specialized. So it has been broken down into separate sections here. Each section should be fairly independent. \layout Section \begin_inset LatexCommand \label{sec:Archives} \end_inset Archives \layout Standard ArX uses archives to store all of the revisions of a project. As explained earlier, archives have a symbolic name (like \family typewriter dcoyote@yoyodyne \family default ), and an address (like \family typewriter /home/dcoyote/yoyodyne \family default ). You can have multiple archives on the same machine or multiple machines. \family typewriter make-archive \family default creates archives and registers them for you. \family typewriter archives \family default lists, registers and unregisters archives. If you need to move an archive, you only need to physically move or copy the archive directory to its new location and re-register the archive. \layout Standard Most of the time, you do not have to register archives with \family typewriter archive \family default s. You can browse archives and get revisions by specifying the complete URI, and that will register the archive for you. \layout Subsection \begin_inset LatexCommand \label{sub:Branches and Revisions} \end_inset Branches and Revisions \layout Standard Within an archive are different branches. Branches are a basic way of splitting up work so that people are free to work out improvements without directly upsetting the main development branch. Branches have a hierarchical structure, and can be any number of levels deep. For example, gcc developers might set up a branch called \family typewriter gcc \family default . Someone else might be working on a new parser, so they make a branch called \family typewriter gcc.new-parser \family default . During the course of their work, the developers working on the new parser might make a branch for improving compilation speed called \family typewriter gcc.new-parser.speed \family default . They might make another branch for handling java and call it \family typewriter gcc.new-parser.java \family default . The branch names are purely for human consumption, and do not enforce any real relation between branches. For example, \family typewriter gcc.new-parser.java \family default might be completely unrelated to gcc or the new parser at all. \layout Standard Within each branch are revisions. These are numbered starting from zero. A revision is a snapshot of the state of a project. For example, revision 66 might be the project just after some speed improvement s have been implemented. Revision 75 might be the project once all of the bugs in the speed improvements are worked out. Revision 76 might be the project once the docs are updated to reflect the new speedups. And so on. A revision is specified with a leading comma \begin_inset Quotes eld \end_inset , \begin_inset Quotes erd \end_inset to distinguish it from a branch. So revision 66 of \family typewriter gcc.new-parser \family default would be \family typewriter gcc.new-parser,66 \family default . \layout Standard To summarize, the complete syntax for specifying a project is \layout LyX-Code archive/branch.subbranch,revision \layout Standard If you have defined your default archive, you can omit the archive. There are a number of cases where you may want to specify just an archive. If it is possible for the archive to be confused with a branch or revision, you must follow the archive name with a slash \begin_inset Quotes eld \end_inset / \begin_inset Quotes erd \end_inset . For example, to browse the contents of archive \family typewriter spanza@example.org \layout LyX-Code arx browse spanza@example.org/ \layout Standard Otherwise, ArX will think that you are trying to browse the \family typewriter spanza@example.org \family default branch in your default archive. \layout Subsection Cached Revisions \layout Standard Arx does not store the full text of all revisions in the archive. Instead, it currently stores the first revision and subsequent patches. This can be quite slow. For example, if you have 1000 revisions, each time you \family typewriter get \family default the latest revision, ArX has to get and apply 999 patches to get to the most recent revision. For that reason, you can cache revisions in the archive. Running \family typewriter \begin_inset Quotes eld \end_inset archive-cache --add \begin_inset Quotes erd \end_inset \family default will create a pristine tree of the latest revision and store it in the archive. This has to do all of the patching, but subsequent \family typewriter get \family default 's won't have to. This uses up additional space in the archive, because it is storing a tarball of an entire project tree and all of the patches. If you need to reclaim the space, \family typewriter \begin_inset Quotes eld \end_inset archive-cache --delete \begin_inset Quotes erd \end_inset \family default will remove it. Finally, \family typewriter \begin_inset Quotes eld \end_inset archive-cache \begin_inset Quotes erd \end_inset \family default without any options will tell you which revisions have been cached. \layout Subsection Remote Archives \layout Standard Remote archives are simply archives that are not accessible through the local filesystem. In practice, remote archives are the principal method for distributing software through ArX. For example, remote archives can be pushed to (e.g. mirroring a local archive to a web server) or pulled from (e.g. to download software from that web server). ArX uses the gnome-vfs libraries to access the remote archives over standard networking protocols. That means that if gnome-vfs can see an archive, then ArX can as well. In particular, ArX can access remote archives using http with webDAV, ftp, ssh, and sftp \begin_inset Foot collapsed false \layout Standard For sftp to work, you must have auto-login enabled. \end_inset . In addition, if you can not install webDAV, there is an option to use http with explicit lists. \layout Standard The first thing that you have to do is set up the (s)ftp, ssh, or http server on the remote machine. ArX does NOT have to be installed. \layout Subsubsection HTTP with webDAV \layout Standard There are two ways that http access can work. ArX needs to list directories, and plain http does not provide that. HTTP with webDAV is the recommended and most reliable way. \layout Standard To configure webDAV with apache, this usually involves installing the mod_dav module. This will work with Apache 1.3 or later. It does not require Apache 2. Then you have to add something like the following to the conf file for apache: \layout LyX-Code \layout LyX-Code DAV On \layout LyX-Code AllowOverride FileInfo AuthConfig Limit \layout LyX-Code Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec \layout LyX-Code \layout LyX-Code Order allow,deny \layout LyX-Code Allow from all \layout LyX-Code \layout LyX-Code \layout LyX-Code Order deny,allow \layout LyX-Code Deny from all \layout LyX-Code \layout LyX-Code \layout Standard You might have to change the first line of that to make it point to where your archives are. \layout Subsubsection HTTP with Explicit lists \layout Standard If you are unable to install webdav support on your server, you can also generate .listing files that contain a listing of a directory. You do this with \family typewriter update-listing \family default . For example, once you have created an archive, you can tell ArX to keep the .listing files to the archive up-to-date with a command like \layout LyX-Code arx update-listing -a sftp://dquixote@example.org/public_html/archive \layout Standard For long latency links, this can significantly increase the time to commit and mirror. If you no longer need to keep the .listing files up-to-date, then \layout LyX-Code arx update-listing -d sftp://dquixote@example.org/public_html/archive \layout Standard will stop ArX from updating them. \layout Subsubsection Accessing the Archives \layout Standard To access archives, just use the ordinary URI notation. Specifically \layout LyX-Code ftp://[user@]host/dir \layout LyX-Code sftp://[user@]host/dir \layout LyX-Code ssh://[user@]host/dir \layout LyX-Code http://[user@]host[:port]/dir \layout LyX-Code https://[user@]host[:port]/dir \layout LyX-Code dav://[user@]host[:port]/dir \begin_inset Foot collapsed false \layout Standard This is only to access webdav repositories using gnome-vfs 2.10 or greater. Previous versions of gnome-vfs just use the http:// notation. \end_inset \layout Standard ArX saves the locations in your \family typewriter .arx \family default directory. For ftp and http, passwords are still transferred in plain text. So securely writing to remote archives requires you to use sftp, ssh, or https. Note that the same archive can be registered using different protocols. For example, suppose that you have a website on the machine \family typewriter example.org \family default rooted at \family typewriter /home/dcoyote/public_html/archive \family default . Through a web browser, it appears at \family typewriter http://example.org/~dcoyote/archive \family default . Since you can log in to the sftp server, you can register the archive as \layout LyX-Code arx archives --add sftp://dcoyote@example.org//home/dcoyote/public_html/archive \layout Standard while someone who wanted just read access could register it as \layout LyX-Code arx archives --add http://example.org/~dcoyote/archive \layout Standard Note that ArX automatically gets the name of the archive from the archive itself. In fact, in general you do not have to register archives at all, since ArX will automatically register them for you. For example, to browse the previous archive, you can type \layout LyX-Code arx browse http://example.org/~dcoyote/archive/ \layout Standard The trailing slash \begin_inset Quotes eld \end_inset / \begin_inset Quotes erd \end_inset is required so that ArX doesn't look for an archive at \layout LyX-Code http://example.org/~dcoyote/ \layout Standard with a branch named \family typewriter archive \family default . \layout Subsection \begin_inset LatexCommand \label{sub:Mirrors} \end_inset Mirrors \layout Standard Suppose that you do all of your work on a laptop, but you also have access to a web server. To share your work with the world, you want to copy your laptop archive to the web server. Alternately, suppose that someone else has published an archive. You would like to have a local copy on your laptop for when you don't have access to the network. You can use mirrors to manage copies of archives. \layout Standard Mirrors are not true copies, in that there are certain restrictions when using them. In particular, you can not commit new revisions to an archive. This prevent the case where one person commits a revision to the master archive, and another person commits a revision with the same name to the mirror. Having two different revisions with the same name but different contents will cause confusion, so ArX prevents it. \layout Subsubsection Publishing a local archive \layout Standard As a concrete example, suppose you have an archive locally and a remote machine that you can access through sftp which also serves as a web server. Then the local archive named \family typewriter dcoyote@example.org-archive \family default might be at \layout LyX-Code file:///home/dcoyote/archive/ \layout Standard The remote archive could be at \layout LyX-Code sftp://dcoyote@example.org//home/dcoyote/public_html/archive/ \layout Standard and it can also be accessed by the web at \layout LyX-Code http://example.org/~dcoyote/archive/ \layout Standard To create the remote mirror, it is \layout LyX-Code arx make-archive --mirror dcoyote@example-archive \backslash \layout LyX-Code sftp://dcoyote@example.org//home/dcoyote/public_html/archive \layout Standard Since the remote archive will also be available over plain http, you need to tell ArX to update the .listing files \layout LyX-Code arx update-listing -a sftp://dcoyote@example.org//home/dcoyote/public_html/archiv e \layout Standard Now if you look at the archive registration, you will see \layout LyX-Code $ arx archives dcoyote@example.org-archive \layout LyX-Code dcoyote@example.org-archive \layout LyX-Code file:///home/dcoyote/archive \layout LyX-Code sftp://dcoyote@example.org//home/dcoyote/public_html/archive \layout Standard So the single archive dcoyote@example.org--archive has two locations associated with it. The first listed location will always be the one used for \family typewriter get \family default , \family typewriter commit \family default , etc., unless you specifically use the other uri. For example, \layout LyX-Code arx get dcoyote@example.org-archive/foo \layout Standard will use the local (file:///) archive to complete the get. If you want to test the mirror, you can use the uri instead of the name \layout LyX-Code arx get sftp://dcoyote@example.org//home/dcoyote/public_html/archive/foo \layout Standard and ArX will get the \family typewriter foo \family default project from the remote mirror. \layout Standard Finally, to populate the mirror, you use the \family typewriter mirror \family default command and specify the source and destination \layout LyX-Code arx mirror dcoyote@example-archive/ \backslash \layout LyX-Code file:///home/dcoyote/archive \backslash \layout LyX-Code sftp://dcoyote@example.org//home/dcoyote/public_html/archive \layout Standard This can get quite tedious to type, so you can shorten the uri's as long as they are unique. That is \layout LyX-Code arx mirror dcoyote@example-archive/ file sftp \layout Standard will do the same thing, as will even \layout LyX-Code arx mirror dcoyote@example-archive/ f s \layout Standard By default, ArX will mirror everything from one archive to the other. You can restrict what will be mirrored by adding it to the archive name. So if you have the projects \family typewriter foo \family default and \family typewriter bar \family default , \layout LyX-Code arx mirror dcoyote@example-archive/foo file sftp \layout Standard will only mirror project \family typewriter foo \family default . \layout Standard Finally, for other people to access it, they will register the archive with the http uri \layout LyX-Code arx archives -a http://example.org/~dcoyote/archive \layout Standard You can also register this location, in which case the output of \family typewriter arx archives \family default would be \layout LyX-Code dcoyote@example--projects \layout LyX-Code file:///home/dcoyote/archive \layout LyX-Code sftp://dcoyote@example.org//home/dcoyote/public_html/archive \layout LyX-Code http://example.org/~dcoyote/archive \layout Standard This might be useful to check that the .listing files have been updated correctly. \layout Subsubsection Making a local copy of a remote archive \layout Standard Another case where mirroring might come in handy is if there is a remote mirror that you want to make a local copy of. Working from the above example, suppose you are Sancho Panza, and you want to have a local copy of Don Quixote's archive. You might do this so that you don't have to wait on the network, or you might want to work where you are disconnected from the network entirely. So you would start with an archive registration like \layout LyX-Code dcoyote@example-archive \layout LyX-Code http://example.org/~dcoyote/archive \layout Standard To make a local archive, you might do something like \layout LyX-Code arx make-archive --mirror dcoyote@example.org-archive \backslash \layout LyX-Code file:///home/spanza/dquixote-archive \layout Standard Then populating it would be \layout LyX-Code arx mirror dcoyote@example.org-archive/ http file \layout Standard This will give you an archive registration like \layout LyX-Code dcoyote@example-archive \layout LyX-Code http://example.org/~dcoyote/archive \layout LyX-Code file:///home/spanza/dquixote-archive \layout Standard But this is not quite what you want. When ArX does a \family typewriter get \family default , it will default to looking at the remote archive. To make ArX default to looking at the local mirror, you can use the \family typewriter --make-default \family default option to \family typewriter archives \layout LyX-Code arx archives --make-default dcoyote@example--projects file \layout Standard Once again, you can abbreviate the uri. This will put the \family typewriter file:/// \family default uri first, so the registration will become \layout LyX-Code dcoyote@example--projects \layout LyX-Code file:///home/spanza/dquixote-archive \layout LyX-Code http://example.org/~dcoyote/archive \layout Section \begin_inset LatexCommand \label{sec:Branching-and-Merging} \end_inset Branching and Merging \layout Standard Suppose someone (Bob) is writing a sorting program, such as the unix sort(1). Bob just started, so he has only implemented a generic bubble sort. That works well enough for Bob, so he is now concentrating on improving the option handling. Alice, on the other hand, likes Bob's program, but needs a faster sorting algorithm. So she wants to work on improving the sorting algorithm while Bob works on the option handling. Eventually, either Bob will merge Alice's work back into the original program, or Alice will merge Bob's work into her version. ArX handles this sort of situation with branches and merges. \layout Subsection Initial Branching \layout Standard So let's start again from the beginning. Bob has written a sorting program and published it as \family typewriter bob@foo.org/sort.bob \family default . It currently has 23 revisions from \family typewriter bob@foo.org/sort.bob,0 \family default to \family typewriter bob@foo.org/sort.bob, \family default 22., as shown in Figure \begin_inset LatexCommand \ref{cap:Bob's-original-revisions} \end_inset . \layout Standard \begin_inset Float figure wide false collapsed false \layout Standard \align center \begin_inset Graphics filename /home/boo/arx/arx/docs/bob_orig.eps lyxscale 30 scale 30 \end_inset \layout Caption \begin_inset LatexCommand \label{cap:Bob's-original-revisions} \end_inset Bob's original revisions \end_inset Alice wants to start from the most recent revision, 22, to implement the new sorting algorithm. To do that, she creates a branch in her own archive alice@bar.org. She will create a branch called sort.bob.quick to denote that she is working on a quicksort implementation. To create the branch, she starts by typing \layout LyX-Code arx get bob@foo.org/sort.bob sort_quick \layout LyX-Code cd sort_quick \layout LyX-Code arx fork alice@bar.org/sort.bob.quick \layout Standard This will create a directory \family typewriter sort_quick \family default with the new branch, but not commit anything to the archive. To actually create the new branch in the archive, she just commits \layout LyX-Code arx commit -s \begin_inset Quotes eld \end_inset branch to implement quicksort \begin_inset Quotes erd \end_inset \layout Standard Now she can use the usual commands to make successive revisions, giving Figure \begin_inset LatexCommand \ref{cap:Alice's-branch} \end_inset . \layout Standard \begin_inset Float figure wide false collapsed false \layout Standard \align center \begin_inset Graphics filename /home/boo/arx/arx/docs/alice_branch.eps lyxscale 30 scale 30 \end_inset \layout Caption \begin_inset LatexCommand \label{cap:Alice's-branch} \end_inset Alice's branch \end_inset \layout Subsection Merge \layout Standard So Alice is happily hacking along, ripping out the bubble sort and implementing the new quick sort. In the meantime, Bob has not been idle. He implemented some fancy new option parsing with five new revisions, 23, 24, 25, 26 and 27. Alice is not entirely sure what Bob has been up to, but she can find out with \family typewriter missing \family default . She types \layout LyX-Code arx missing bob@foo.org/sort.bob \layout Standard and ArX will print out all of the patches that she doesn't have yet (patches 23, 24, 25, 26, and 27). She looks at those changes, and decides to incorporate all of those changes into her branch. So she merges those changes in \layout LyX-Code arx merge \family typewriter bob@foo.org/sort \family default . \family typewriter bob \layout Standard There are a number of ways that changes can conflict (see Appendix \begin_inset LatexCommand \ref{cha:Conflicts} \end_inset ). By default, ArX uses a three-way merge to apply the changes in Bob's tree to Alice's tree. ArX can also merge by looking at the patches that Bob has applied to make \family typewriter bob@foo.org/sort.bob,22 \family default become \family typewriter bob@foo.org/sort.bob,27 \family default , gathering it into one big patch and applying it to Alice's \family typewriter sort_quick \family default tree. \layout LyX-Code arx merge --algo patch \family typewriter bob@foo.org/sort \family default . \family typewriter bob \layout Standard Either method is fairly sophisticated, handling a number of cases automatically. For everything but modification of file contents (i.e. renames, deletes, metadata changes), the two methods are identical. For example, even if a file has moved, ArX will still know which file to modify. But sometimes there are problems. Bob may have made incompatible changes to a file that Alice modified. \layout Standard The three-way merge is slightly better at avoiding conflicts, so it is the default. But when conflicts are inevitable, the real difference between the two methods is how conflicts are resolved. When there are conflicts in file contents, the three-way merge method will leave four files in the project tree: The original tree file, the sibling file, the ancestor file, and the output of diff3 when it tried to merge the three. The diff3 file has inline conflict markers similar to what CVS conflicts give. To resolve the conflict, you can edit the diff3 output and remove the other three files. You can also run a GUI three-way merge tool on the three files: tree, ancestor, and sibling. You can even have ArX pop up a merge tool automatically when it detects conflicts. See Appendix \begin_inset LatexCommand \ref{cha:Sample-Merge-Scripts} \end_inset for details. \layout Standard When there are conflicts using the big cumulative patch method, ArX leaves three files: the original tree file, a modified file with as many of the hunks of the patch applied as possible, and a file with the rejected hunks. \layout Standard For any conflict, ArX will print out an error message detailing what went wrong. Alice can retrieve these messages with \family typewriter arx resolve \family default . Once Alice cleans up all of the problems, she must tell ArX that the conflicts have been resolved with \family typewriter arx resolve \family default . Only then will she be able to commit \layout LyX-Code arx commit -s \begin_inset Quotes eld \end_inset Merge from sort.bob,27 \begin_inset Quotes erd \end_inset \layout Standard Her branch will then incorporate Bob's improvements, giving Figure \begin_inset LatexCommand \ref{cap:Alice's-branch-updated} \end_inset . \layout Standard \begin_inset Float figure wide false collapsed false \layout Standard \align center \begin_inset Graphics filename /home/boo/arx/arx/docs/alice_update.eps lyxscale 30 scale 30 \end_inset \layout Caption \begin_inset LatexCommand \label{cap:Alice's-branch-updated} \end_inset Alice's branch updated with Bob's improvements \end_inset \layout Subsection Replay \layout Standard The \family typewriter merge \family default command looks at the differences as a large, amalgamated whole. Sometimes, it can be advantageous to consider differences patch by patch. This is what replay does. If Alice had instead typed \layout LyX-Code arx replay \family typewriter bob@foo.org/sort \family default . \family typewriter bob \layout Standard then ArX would instead have tried to first apply patch 23 onto Alice's tree, then patch 24, then patch 25, etc. If, along the way, any of those patches caused a conflict, ArX stops with that patch and lets you fix up the tree before continuing. For example, suppose patch 24 had a conflict. \family typewriter sort_quick \family default will contain the result of ArX's attempt to patch up to patch 24. Once Alice fixed up the \family typewriter sort_quick \family default directory, she can just repeat the same command \layout LyX-Code arx replay \family typewriter bob@foo.org/sort \family default . \family typewriter bob \layout Standard and ArX will attempt to continue the update. If there are other conflicts, Alice can continue fixing conflicts and repeating the update until she reaches Bob's current version. Assuming that Alice resolved conflicts the same way, this should give exactly the same result as Figure \begin_inset LatexCommand \ref{cap:Alice's-branch-updated} \end_inset . \layout Standard However, replay also offers the possibility of selectively applying patches. Suppose Alice didn't like all of Bob's patches, but only liked patches 25 and 27. She could have incorporated those changes, and only those changes, with the commands \layout LyX-Code arx replay --exact \family typewriter bob@foo.org/sort \family default . \family typewriter bob \family default ,25 \layout LyX-Code arx replay --exact \family typewriter bob@foo.org/sort \family default . \family typewriter bob \family default ,27 \layout Standard This will apply patches 25 and 27 to the tree. She can also do it in one go by putting the patches names in a file and using the \family typewriter --list \family default option. \layout Standard Unfortunately, once she uses selective patching, she can't use \family typewriter merge \family default or \family typewriter replay \family default in their generic form anymore. They will both want to incorporate the patches that she deliberately skipped. ArX currently does not have a means of marking certain patches as unwanted. If she wants to continue to get updates from Bob, she will always have to use the \family typewriter --exact \family default or \family typewriter --list \family default options. \layout Subsection Merging Back \layout Standard Alice can continue hacking, using \family typewriter merge \family default or \family typewriter replay \family default to update her branch with Bob's changes. Eventually, Bob may want to integrate Alice's changes. This is as simple as \layout LyX-Code arx merge alice@bar.org/sort.bob.quick \layout Standard This will incorporate all of Alice's patches. ArX is smart enough to know that it really only needs the patches after patch 27 from Bob, because \family typewriter alice@bar.org/sort.bob.quick,4 \family default integrated Bob's branch up to patch 27 into Alice's. As usual, this patching may cause a conflict. Once that is cleaned up, a commit will lead to Figure \begin_inset LatexCommand \ref{cap:Bob's-branch-star-merge'd} \end_inset . \layout Standard \begin_inset Float figure wide false collapsed false \layout Standard \align center \begin_inset Graphics filename /home/boo/arx/arx/docs/bob_star_merge.eps lyxscale 30 scale 30 \end_inset \layout Caption \begin_inset LatexCommand \label{cap:Bob's-branch-star-merge'd} \end_inset Bob's branch star-merged with Alice's \end_inset \layout Standard As Alice and Bob continue improving their respective branches, they can continue to merge with each other with \family typewriter merge \family default . \layout Subsection Bug Fix Branches \layout Standard There are other reasons for making a branch. If you have made a release of your software, and want to fix issues in that release without affecting current development, then you can branch from that release. For example, suppose that Bob had made a release of \family typewriter bob@foo.org/sort.bob,20 \family default \begin_inset Foot collapsed true \layout Standard It is usually best to use tags (Section \begin_inset LatexCommand \ref{sub:Tags} \end_inset ) to mark releases rather than using a specific revision number. \end_inset . Later, after Bob has merged in the support for Alice's work on quick sort, someone finds a bug in his implementation of bubble sort (how embarrasing!). Bob can't make the fix in the current line of development, because the bubble sort has been removed. Bob also can't release the current line of development because the project is not in a releaseable state. Instead, he branches from the release and fixes the bug on the branch. Specifically \layout LyX-Code arx get bob@foo.org/sort.bob,20 fixed \layout LyX-Code cd fixed \layout LyX-Code (fix the bubble sort bug) \layout LyX-Code arx fork bob@foo.org/sort.bob.fixed \layout LyX-Code arx commit -s \begin_inset Quotes eld \end_inset Fixed the bubble sort \begin_inset Quotes erd \end_inset \layout Standard Bob can now make a new release with \family typewriter bob@foo.org/sort.bob.fixed,0 \family default , and it will only have the fix to the bubble sort bug. \layout Standard If it turns out that the bug has already been fixed in the current line of development, Bob can pull in just that change. For example, if there is a typo in the help screen that has been fixed in \family typewriter bob@foo.org/sort.bob,30 \family default , then Bob can apply just that patch with \layout LyX-Code arx replay --exact bob@foo.org/sort.bob,30 \layout Standard See also Section \begin_inset LatexCommand \ref{sub:Breaking-up-patches} \end_inset for how to apply patches with even finer granularity. \layout Section Remote Cooperation and Publishing Your Work \layout Subsection Tags \begin_inset LatexCommand \label{sub:Tags} \end_inset \layout Subsubsection Release Markers \begin_inset LatexCommand \label{sub:Release-Markers} \end_inset \layout Standard If you wish to distribute your work, you can create and update a mirror as described in section \begin_inset LatexCommand \ref{sub:Mirrors} \end_inset . Then other people can register your archive and get the latest revision using \family typewriter arx get \family default . However, people may not want to continuously follow every little spelling and off-by-one bugfix. They only want significant, well-tested improvements. You can accommodate them by using symbolic names to mark certain revisions as stable. For example, consider the situation given in Figure \begin_inset LatexCommand \ref{cap:Bob's-original-revisions} \end_inset . If Bob is happy with the state of the tree at that point, then he can create a release marker with \layout LyX-Code arx tag bob@foo.org/sort.bob.release bob@foo.org/sort.bob \layout Standard This creates a revision, \family typewriter bob@foo.org/sort.bob.release,0 \family default , which acts as a symbolic name for the last revision of \family typewriter bob@foo.org/sort.bob \family default (in this case, that would be \family typewriter bob@foo.org/sort.bob,22 \family default ). Bob can run this command whenever he wants to make a release. An interested user can get the latest release with \layout LyX-Code arx get bob@foo.org/sort.bob.release \layout Standard Because \family typewriter bob@foo.org/sort.bob.release \family default is just a symbolic name, you can not fork directly from it. Rather, you must fork from the referenced revision. \layout Standard You can also use tags to just give a different name for a particular revision. For example, suppose you had a branch \family typewriter myproduct \family default , and your marketing experts wanted to name the next version \family typewriter v0.0.1 \family default . Then \layout LyX-Code arx tag myproduct myproduct.v0.0.1 \layout Standard will create a revision that you can get with \layout LyX-Code arx get myproduct.v0.0.1 \layout Subsubsection Collections \layout Standard You can also use \family typewriter tag \family default to mark a collection of projects. So if you have the directory structure \layout LyX-Code foo ----> Contains the project foo.main \layout LyX-Code foo/bar ----> Contains the project bar.main \layout Standard then you can mark the whole collection of projects with \layout LyX-Code arx tag foo.collection foo.main bar.main bar \layout Standard That is, you first specify the head project ( \family typewriter foo.main \family default ). For the tail projects, you specify the project name ( \family typewriter bar.main \family default ), and the subdirectory that it goes into ( \family typewriter bar \family default ). Then \layout LyX-Code arx get foo.collection \layout Standard will download both \family typewriter foo.main \family default and \family typewriter bar.main \family default , and put \family typewriter bar.main \family default into the \family typewriter bar \family default subdirectory of \family typewriter foo.main \family default . \layout Standard You can have as many sub-projects as you wish. For large, complicated projects, you can read in a list of projects from a file. The format is \layout LyX-Code tag-name \layout LyX-Code head-project \layout LyX-Code sub-project sub-dir \layout LyX-Code sub-project sub-dir \layout LyX-Code ... \layout Standard Then you read it in with \layout LyX-Code arx tag -f FILE \layout Subsubsection Floating Tags \layout Standard With these large, complicated projects, another problem emerges. When you define a tag, it will point to a particular revision. In the previous section, running \layout LyX-Code arx tag foo.collection foo.main bar.main bar \layout Standard will create a tag \family typewriter foo.collection,0 \family default that points to the last revision of \family typewriter foo.main \family default (perhaps \family typewriter foo.main,12 \family default ) and the last revision of \family typewriter bar.main \family default (perhaps \family typewriter bar.main,7 \family default ). If you continue to work on \family typewriter foo.main \family default and \family typewriter bar.main \family default , then running \layout LyX-Code arx get foo.collection \layout Standard will always give you \family typewriter foo.main,12 \family default and \family typewriter bar.main,7 \family default . On the other hand, if you use a floating tag \layout LyX-Code arx tag --float foo.head foo.main bar.main bar \layout Standard then \family typewriter foo.head \family default will always point to the latest revisions of foo.main and bar.main. You can now always get the latest version of the entire collection with \layout LyX-Code arx get foo.head \layout Standard If you just want to update a copy of the tree, then it is just \layout LyX-Code arx merge foo.head \layout Subsubsection Limitations \layout Standard Tags will show up as ordinary branches in \family typewriter arx browse \family default , but they have a few restrictions. In particular, \family typewriter tree-cache \family default , \family typewriter replay \family default , \family typewriter fork \family default , \family typewriter file-diff \family default , \family typewriter file-orig \family default , \family typewriter file-undo \family default , and \family typewriter get-patch \family default will not work with tags. \family typewriter diff \family default does not work directly with tags, but there is a \family typewriter --recursive \family default option to handle collective tags. \family typewriter archive-cache \family default , \family typewriter get \family default , \family typewriter export \family default , \family typewriter missing \family default , and \family typewriter merge \family default will work even with collective tags. So \family typewriter get \family default gets all of the different projects, \family typewriter merge \family default updates the main project and subprojects, etc. \family typewriter merge \family default also has a \family typewriter --recursive \family default option, which updates all of the subdirectories, not just the ones listed in the tag. The \family typewriter --recursive \family default is equivalent to running \family typewriter merge \family default in each subdirectory. So it will not update a subdirectory to a new branch, while using merging with a tag could. \layout Subsection export \layout Standard You may decide that you do not want to make people use ArX just to get a revision. Even without other people involved, you may want to use your work in different environments that do not have ArX installed. \family typewriter export \family default can create a tree without any of the ArX control files and, for your convenienc e, a tarball of this tree. For example, if the latest revision of hello.main is patch 6, then \layout LyX-Code arx export --tarball hello.main hello \layout Standard will create a tarball in the current directory named hello.6.tar.gz. If you desire, you can include GNU-style changelogs with the \family typewriter --changelog \family default option. \family typewriter export \family default will also work with tags \begin_inset LatexCommand \ref{sub:Tags} \end_inset . \layout Subsection Applying patches directly \layout Standard Sometimes it is useful to generate and apply patches directly. For example, you might fix a bug in a project, but have no means of publishing the archive. So you want to just mail the patch directly to the upstream author. \layout LyX-Code arx diff -o diffdir \layout Standard \family typewriter will \family default create a patch in the \family typewriter diffdir \family default directory. You can simply tar up that directory and mail it. \layout Standard If you have made your own archive with several patches, you can still bundle all of the changes together with \family typewriter diff \family default . You just supply \family typewriter diff \family default with the last upstream revision. For example, given the situation in Figure \begin_inset LatexCommand \ref{cap:Alice's-branch} \end_inset , Alice can create a patch of all of the work she has done with \layout LyX-Code arx diff -o diffdir --revision bob@foo.org/sort.bob,22 \layout Standard Alternately, you may wish to give the patches back piecemeal, so that the upstream author can take only what they want. You can get a specific patch with \family typewriter get-patch \family default . So again with the example in Figure \begin_inset LatexCommand \ref{cap:Alice's-branch} \end_inset , Alice can get all of the indiviual patches with \layout LyX-Code arx get-patch alice@bar.org/sort.bob.quick,0 alice.0 \layout LyX-Code arx get-patch alice@bar.org/sort.bob.quick,1 alice.1 \layout LyX-Code arx get-patch alice@bar.org/sort.bob.quick,2 alice.2 \layout LyX-Code arx get-patch alice@bar.org/sort.bob.quick,3 alice.3 \layout Standard This will put the patches into the directories \family typewriter alice.0 \family default , \family typewriter alice.1 \family default , \family typewriter alice.2 \family default , and \family typewriter alice.3 \family default . \layout Standard If you want to put together some, but not all, of the patches, you can create a new project tree with the upstream author's latest version. Then you can apply the specific patches with \family typewriter replay \family default and \family typewriter diff \family default will produce a patch that encompasses all of the changes. With the Alice/Bob example \layout LyX-Code arx get bob@foo.org/sort.bob,22 sort \layout LyX-Code cd sort \layout LyX-Code arx replay --exact alice@bar.org/sort.bob.quick,1 \layout LyX-Code arx replay --exact alice@bar.org/sort.bob.quick,3 \layout LyX-Code arx diff -o patch_1_3 \layout Standard This will put a patch in the directory \family typewriter patch_1_3 \family default which agglomerates the patches \family typewriter alice@bar.org/sort.bob.quick,1 \family default and \family typewriter alice@bar.org/sort.bob.quick,1 \family default . \layout Standard On the receiving end, if the original author has a project tree in directory \family typewriter foo \family default and the patch unpacked into the directory \family typewriter diffdir \family default , then \layout LyX-Code arx dopatch diffdir foo \layout Standard will apply the patch. \layout Subsection \begin_inset LatexCommand \label{sub:Multiple-commiters-(a} \end_inset Multiple commiters (a la CVS) \layout Standard If you have a particularly large, active project, you may have many different people updating various parts concurrently. You want to allow the main development branch to be updated by multiple people. This is the usual style of development with large projects using CVS. There are a few ways to do this in ArX. \layout Standard The first is to just make the archive directly writeable by all of the developer s. If you are all in the same place, you might do this with NFS. However, you do have to be careful with permissions and umask. Otherwise, one developer committing changes may make it impossible for other developers to commit. \layout Standard If you are in separate places, you can give all of the developers accounts to a shared filesystem, once again being careful about permissions and umask. If permissions and umask problems are insurmountable, or you do not wish to make new accounts for every person who is vaguely interested in the project, then you can make a single account that all of the developers can use to update the archive with sftp. That means making a new account for each project. It also makes it more difficult to audit the activity in the source tree, since there is only one user-id associated with all of the changes. \layout Standard One solution is to designate a person as an integrator. Developers branch off of the integrator's main line of development. When the developer is ready, they send a merge request to the integrator. The integrator applies the change to a test tree, runs any tests, and commits. This solution is nice in that it does not require giving out accounts to anyone. However, with a busy project, the integrator can get overwhelmed. \layout Standard Fortunately, this process can be automated with a patch queue manager (PQM). A nice PQM is bundled with ArX in the \family typewriter tools/pqm \family default directory. The idea is to have a special PQM account that manages the main line of development. Then developers branch off of this main line of development. When the developer is ready, they send a merge request to the PQM account (e.g. through a signed email). The PQM account attempts the merge, and, if successful, commits the change. If the merge fails because of conflicts, then nothing is committed. More documentation can be found in \family typewriter tools/pqm \family default . \layout Section \begin_inset LatexCommand \label{sec:Reverting-development} \end_inset Reverting development \layout Standard Sometimes, you want to undo some of the changes that you have made. \layout Subsection Before you commit \layout Standard If you haven't committed the change to the archive and you only want to revert one file, you can use \family typewriter file-undo \family default . That is, to undo the changes made to file \family typewriter foo \family default , you would type \layout LyX-Code arx file-undo foo \layout Standard However, \family typewriter file-undo \family default will not work properly if you deleted the file with \begin_inset Quotes eld \end_inset \family typewriter arx rm \family default \begin_inset Quotes erd \end_inset or moved it with \begin_inset Quotes eld \end_inset \family typewriter arx mv \family default \begin_inset Quotes erd \end_inset . You can also decide to undo a file back to a particular revision by specifying that revision \layout LyX-Code arx file-undo foo hello.main.1.0,11 \layout Standard Using a revision other than the most recent may require ArX to get that old revision, which can be time consuming. If this is a problem, you can add that revision to your pristine trees. \layout Standard If you want to undo the changes made to a number of files, or you used \begin_inset Quotes eld \end_inset \family typewriter arx rm \family default \begin_inset Quotes erd \end_inset or \begin_inset Quotes eld \end_inset \family typewriter arx mv \family default \begin_inset Quotes erd \end_inset on a file you want to undo, then you have to use \family typewriter undo \family default with those paths as extra arguments. That is, if you want to undo the files \family typewriter foo \family default and \family typewriter bar \family default plus everything in the directory \family typewriter bat \family default , you can use the command \layout LyX-Code arx undo foo bar bat/ \layout Standard If the changes in the directory \family typewriter bat/ \family default depend on changes elsewhere, then ArX will let you know what you need to include. If you want to undo everything that has been done since the last commit, just use \family typewriter undo \family default without any arguments. \layout Standard \family typewriter file-undo \family default will store a copy of the old file in ,,file-name, so you can get back your changes by copying that file back. \family typewriter undo \family default will store the changes in a directory ,,undo-N, with N being the smallest number not already taken. To get the changes back, you can use \family typewriter redo \family default . If you don't give \family typewriter redo \family default any arguments, \family typewriter redo \family default will just use the largest numbered ,,undo-N directory. Of course, if you decide that you really don't need the changes, you can simply delete the ,,file-name files and ,,undo-N directories. ArX will never delete them itself. \layout Standard In summary, \family typewriter file-undo \family default is nice for changes to a single file, because ArX keeps a complete copy of the modified file around. \family typewriter undo \family default only keeps a copy of the differences between the original file and the modified file. \family typewriter file-undo \family default also works for any revision, while \family typewriter undo \family default only works for the current revision. However, there are times when \family typewriter file-undo \family default will not work, while \family typewriter undo \family default always works. \layout Subsection After you commit \layout Standard If you have already committed the changes to an archive, then there are two ways of reverting those changes: Non-destructive and Destructive. \layout Subsubsection Non-destructive revert \layout Standard If you decide that you need to revert changes that have already been committed to an archive, then you need to use the \family typewriter --add \family default option to \family typewriter history \family default . This will make it look like a tree has the patches for a particular revision without actually applying them. So, for example, suppose you really want the most recent revision to look like hello.main,12, but you made some ill-considered changes in patches 13 and 14, then you could run \layout LyX-Code arx get hello.main,12 hello \layout LyX-Code cd hello \layout LyX-Code arx history --add hello.main \layout LyX-Code arx commit -s \begin_inset Quotes eld \end_inset Reverted patches 13 and 14 \begin_inset Quotes erd \end_inset \layout Standard That will create revision patch 15 which will look exactly like revision patch 12 except for the history. Then, if it turns out later that patches 13 and 14 were not such a bad idea, you can still get them. \layout Standard This also lends itself to more complicated scenarios, where not everything in patches 13 and 14 was bad. For example, suppose the changes to directory bat/ were good, but everything else was bad. Then you can use the sequence \layout LyX-Code arx get hello.main,12 hello \layout LyX-Code cd hello \layout LyX-Code arx history --add hello.main \layout LyX-Code arx undo bat/ \layout LyX-Code arx commit -s \begin_inset Quotes eld \end_inset Removed everything in patch 13 and 14 except changes to bat \begin_inset Quotes erd \end_inset \layout Standard This preserves the changes to \family typewriter bat/ \family default but not anything else. \layout Standard Finally, you can use \family typewriter history --add \family default just to synchronize development. Consider a branch hello.branch that, for whatever reason, you want to make exactly the same as hello.main. Perhaps all of the changes that were in \family typewriter hello.branch \family default got integrated in various ways into \family typewriter hello.main \family default , and you now want to re-sync \family typewriter hello.branch \family default . You can accomplish this with \layout LyX-Code arx get hello.main hello \layout LyX-Code cd hello \layout LyX-Code arx history --add hello.branch \layout LyX-Code arx tree-version hello.branch \layout LyX-Code arx commit -s \begin_inset Quotes eld \end_inset Synchronize with main \begin_inset Quotes erd \end_inset \layout Standard Most of the time, though, you would probably just abandon the old branch and make a new one. Otherwise, people may get confused by a branch that changes meaning. \layout Subsubsection Destructive revert \layout Standard You may have accidently committed a file that is extremely large, has corporate secrets, is illegal to distribute, etc. In those cases, you will want to do a destructive revert of your changes and reclaim the space. ArX does not allow you to just remove a revision. That is because someone may have forked from there, and if you replace one revision with a different one, then ArX will get very confused. Essentially, ArX is trying to keep you from changing history. \layout Standard As an example, suppose that revision foo,23 has one of these undesirable files. You can issue the command \layout LyX-Code arx delete-revision foo,23 \layout Standard and ArX will print out a formatted version of the log and prompt you to continue. If you do so, that revision will be replaced with an empty revision. It will have a log just stating that it has been reverted. To continue development, \family typewriter fork \family default from the previous revision \layout LyX-Code arx get foo,22 new_foo \layout LyX-Code cd new_foo \layout LyX-Code arx fork foo \layout Standard and work in the \family typewriter new_foo \family default directory. If you didn't notice the problem until after revisions were added past \family typewriter foo,23 \family default , you can replay those patches \layout LyX-Code arx replay --exact --dir new_foo foo,24 \layout LyX-Code arx replay --exact --dir new_foo foo,25 \layout LyX-Code arx replay --exact --dir new_foo foo,25 \layout LyX-Code ... \layout Standard If you had just used merge, you will get the deleted log message. Not the end of the world, but a minor annoyance. \layout Standard If you want to delete an entire branch, then \family typewriter delete-branch \family default will remove everything, leaving no traces of that branch. For example, \layout LyX-Code arx delete-branch foo \layout Standard will delete everything in the branch \family typewriter foo \family default , including any sub-branches such as \family typewriter foo.bar \family default , \family typewriter foo.bar.baz \family default , etc. This is a powerful command, and ArX prompts you before deleting. \layout Section Properties \layout Subsection Preserving File Permissions \layout Standard ArX allows you to assign arbitrary properties to paths. The primary application for this within ArX is to version permissions. For example, if you want to make sure that the file \family typewriter foo \family default will have its executable bit set, then the command \layout LyX-Code arx property --set arx:user-exec true foo \layout Standard will ensure that. At present, the following properties have predefined meanings \layout LyX-Code arx:user-read \layout LyX-Code arx:user-write \layout LyX-Code arx:user-exec \layout LyX-Code arx:group-read \layout LyX-Code arx:group-write \layout LyX-Code arx:group-exec \layout LyX-Code arx:other-read \layout LyX-Code arx:other-write \layout LyX-Code arx:other-exec \layout Standard If any of these properties are set to true or false, then when that path is checked out (e.g. with get), the appropriate permission bit is set (assuming the file system can accomodate it). \layout Subsection User Defined Properties \layout Standard You can also define your own properties. For example, you can assign a property that tells you what kind of license a file is covered by. If you type \layout LyX-Code arx property --set license GPL foo \layout LyX-Code arx property --set license BSD bar \layout Standard then the license for file \family typewriter foo \family default is set to the GPL and the license for \family typewriter bar \family default is set to the BSD license. Note that, while the properties can be arbitrary, they are designed to work well when they are small. \layout Subsection End-of-Line Conversion \layout Standard By default, ArX does not do any conversion of the end-of-line markers used in files. In the future, ArX may use the arx:eol-style property to do something similar to what Subversion does \begin_inset Foot collapsed true \layout Standard http://svnbook.red-bean.com/en/1.1/svn-book.html#svn-ch-7-sect-2.3.5 \end_inset . \layout Section Hooks \begin_inset LatexCommand \label{sec:Hooks} \end_inset \layout Standard One approach to quality control is to have a modified project tree go through a series of automated tests before the modifications are stored in the archive. A simple example is to make sure that the modified tree will build. Once the patch has gone through, you may wish to automatically perform various actions, such as sending mail about a patch to interested parties. ArX itself uses this feature to update the arx-changes list. \layout Standard ArX supports these two needs through hooks. To use hooks, you create an executable file in \family typewriter ~/.arx/hooks \family default . It can be a shell, Python, or Perl script, or even a full blown C, C++, Java or Lisp application. ArX invokes the hook both just before and just after it has altered an archive by adding categories, branches, versions, or revisions. This occurs when you invoke \family typewriter commit \family default , \family typewriter tag \family default , or \family typewriter mirror \family default . ArX calls the hook with two arguments. The first argument is either \family typewriter pre \family default or \family typewriter post \family default , indicating that the hook is being called either before or after altering the archive. The second argument is one of \family typewriter make-branch \family default or \family typewriter make-revision \family default , indicating what ArX is about to do or has done. That is, the call syntax looks like \layout LyX-Code ~/.arx/hooks (pre|post) make-(branch|revision) \layout Standard In addition, ArX sets the environment variables \family typewriter ARX_TREEROOT \family default to the root of the project tree (if applicable), \family typewriter ARX_PREVIOUS_ARCHIVE \family default , \family typewriter ARX_PREVIOUS_ARCHIVE_URI \family default , \family typewriter ARX_PREVIOUS_BRANCH \family default , and \family typewriter ARX_PREVIOUS_REVISION \family default to the archive, archive uri, branch, and revision of the previous revision, and \family typewriter ARX_ARCHIVE \family default , \family typewriter ARX_ARCHIVE_URI \family default , \family typewriter ARX_BRANCH \family default , \family typewriter ARX_REVISION \family default , and to the archive, archive uri, branch, and revision involved. These can be queried to customize how the hook behaves. As an example, the following shell script will send email about new categories, branches, versions, and revisions in the \family typewriter wlandry@ucsd.edu--arx \family default archive to the arx-changes list \layout LyX-Code #!/bin/sh \layout LyX-Code \layout LyX-Code # Simple mail of patch log \layout LyX-Code \layout LyX-Code pre_post=$1 \layout LyX-Code action=$2 \layout LyX-Code \layout LyX-Code if test $pre_post = "post" ; then \layout LyX-Code if test $ARX_ARCHIVE = "wlandry@ucsd.edu--arx" ; then \layout LyX-Code if test $ARX_ARCHIVE_URI = \backslash \layout LyX-Code "sftp://landry@superbeast.ucsd.edu//home/landry/public_html/ArX/wlandry" ; then \layout LyX-Code if test $action = "make-branch" ; then \layout LyX-Code printf "$ARX_ARCHIVE" | mail -s \backslash \layout LyX-Code "New Branch: $ARX_BRANCH" arx-changes@nongnu.org \layout LyX-Code fi \layout LyX-Code if test $action = "make-revision" ; then \layout LyX-Code arx log --remote --formatted --branch $ARX_REVISION | mail -s \backslash \layout LyX-Code "New Revision: $ARX_REVISION" arx-changes@nongnu.org \layout LyX-Code fi \layout LyX-Code fi \layout LyX-Code fi \layout LyX-Code fi \layout Standard The hook script is executed within the current directory. This script will be executed whenever you alter any archive, so a long complicated script will slow these actions down. When invoked before altering the archive, ArX waits for the hook script to return and aborts if it returns non-zero. When invoked after altering the archive, ArX executes the hook script in the background and ignores the return code. Post-commit hooks are never guaranteed to be invoked. A well timed interrupt could let the transaction finish but prevent the hook from running. \layout Section Patch Logs and Changelogs \layout Standard When committing a change, ArX needs a log file with a Summary: field. If you use the \family typewriter -s \family default option to commit, then ArX will create a log file for you that contains that field. However, you can also create your own log files with custom headers. There are some reserved headers (such as Standard-date:, Renamed-files:, etc.) listed in the help for \family typewriter log \family default , but otherwise you can define any header you like. The log file uses an RFC-822 style format. A colon separates the header and the field, and the field is terminated by a newline that is not followed by a tab. The body is separated from the headers by a blank line. As an example, \layout LyX-Code Summary: Frozzled the foo \layout LyX-Code Mail-results-to: don@example.org, sancho@example.com, \layout LyX-Code dulcinea@example.net \layout LyX-Code Bug-Number: 1605 \newline \newline The foo was blarged by the bar, so I had to frozzle the foo in order to \layout LyX-Code unmome the borogoves. \layout Standard You can then specify that log file with the \family typewriter --log-file \family default option to commit. \layout Standard ArX adds some reserved fields and stores the log as part of the patch. These logs then become part of the revision. When you make a branch, your logs for that new revision appear in the project tree. You can see what versions have gone into a project tree with \family typewriter history \family default . For each of the versions that it lists, you can find out which patches are included with \family typewriter log \family default . \family typewriter log \family default also lets you look at specific headers. A simple example is to look at the \family typewriter New-files: \family default field for all of the patches for the current version of the tree \layout LyX-Code arx log --header Revision --header New-files \layout Standard The \family typewriter Revision \family default header is included because otherwise there is no way to tell which new files belong to which revision. \layout Standard You can also do more complicated things, such as finding when foo.bar.1.0,112 was created and by whom \layout LyX-Code arx log --header Standard-date --header Creator \backslash \layout LyX-Code --branch foo.bar.1.0,112 \layout Standard You can use the \family typewriter --remote \family default option to look at logs for revisions that you don't have in a project tree. For example, if you were unsure whether you wanted to get those revisions at all. \layout Section Making Patches Bigger or Smaller \layout Standard ArX currently does not support directly breaking up one patch into smaller patches or composing multiple patches into one big patch. You can achieve the same effect through some workarounds. \layout Subsection Selective commits \layout Standard Suppose you are happily working on one feature, but along the way you notice and fix a bug in unrelated functionality. You would like to separate the bug fix from the ongoing feature work. Usually, the best way to do this is with extra path arguments to \family typewriter commit \family default . For example, if the features are in file \family typewriter foo \family default , and the bug fix is in file \family typewriter bar \family default , then \begin_inset Quotes eld \end_inset \family typewriter arx commit bar \family default \begin_inset Quotes erd \end_inset will only commit the changes in file \family typewriter bar \family default . You can also select files that have been added, moved, and deleted. ArX performs thorough checks to make sure that you always commit a valid patch. For example, if you were not careful, you might commit a file that is in a directory that does not yet exist in the archive. If you try to make ArX do this, then ArX will tell you what paths need to be added the argument list. \layout Standard If the separation between bug fix and feature is not so clean, such as if the changes occur in the same file, then you can use \family typewriter undo \family default . You run \family typewriter undo \family default on the whole directory, make and commit the bug fix, then \family typewriter redo \family default to get back the work you've done. More information on \family typewriter undo \family default / \family typewriter redo \family default is in Section \begin_inset LatexCommand \ref{sec:Reverting-development} \end_inset . \layout Subsection Breaking up patches \begin_inset LatexCommand \label{sub:Breaking-up-patches} \end_inset \layout Standard Suppose that someone has created a humongous, all-singing, all-dancing patch that adds 12 features, fixes 30 bugs , and, of course, introduces its own. You are only interested in a particular feature which is localized to files foo1, foo2, foo3, etc. To get just the changes to these files, you can do something like \layout LyX-Code arx replay --exact bar.big-patches,13 \layout LyX-Code arx undo -o foo_undo foo1 foo2 foo3 ... \layout LyX-Code arx undo \layout LyX-Code arx redo foo_undo \layout Standard This gets the patch, applies it to your own tree, selectively reverts the feature you want, reverts everything else, and then reapplies the desired feature. \layout Subsection Agglomerating patches \layout Standard Suppose you have a project \family typewriter foo.main \family default , and you want to make a patch that includes patches 122, 133, and 156 all as one big patch. You can do it with something like \layout LyX-Code arx get foo.main,121 foo \layout LyX-Code cd foo \layout LyX-Code arx replay --exact foo.main,122 \layout LyX-Code arx replay --exact foo.main,133 \layout LyX-Code arx replay --exact foo.main,156 \layout LyX-Code arx diff -o big_patch --revision foo.main,121 \layout Standard This gets revision 121, applies the various patches selectively, and then puts the agglomerated patch into the directory \family typewriter big_patch \family default . \layout Section Working with Large Trees \layout Subsection arx edit \layout Standard By default, ArX is set up to be very careful when looking for changes. This means that ArX has to look at the contents of every file before it can decide whether it has changed. This can be prohibitively slow for large projects. So ArX offers another mode of operation where you can promise not to edit a file unless you specifically tell ArX. This approach is similar to what Perforce and Bitkeeper do. \layout Standard You can take advantage of this mode of operation by using the \family typewriter --no-edit \family default option to \family typewriter get \family default . ArX will download the revision and then change the permissions on all of the files to read-only. To edit a file, you have to run \family typewriter arx edit \family default and ArX will change the file to writeable. Then, when you run \family typewriter arx commit \family default , ArX will once again mark the files as read-only. You do not have to run \family typewriter arx edit \family default in order for \family typewriter arx rm \family default , \family typewriter arx mv \family default , and \family typewriter arx property \family default to work. \layout Standard The advantage of this is that when ArX figures out what you have changed for \family typewriter diff \family default or \family typewriter commit \family default , ArX only has to look at the short list of files that you have marked (via \family typewriter edit \family default , \family typewriter rm \family default , \family typewriter mv \family default , and \family typewriter property \family default ). This can reduce the time for these common operations from minutes to near-insta ntaneous. However, some people find this mode of operation incredibly annoying. Others hardly notice it. You only need to use it if you are running into problems. In general, if your project tree is in memory, ArX humms right along. However, if the project tree is not in memory, ArX has to load it from disk which can take a rather long time. Whether your tree is in memory depends on your individual work patterns. \layout Standard If you decide that you want to always work in this mode of operation, you can set to \family typewriter true \family default the \family typewriter no-edit \family default parameter in \family typewriter arx param \family default . Then \family typewriter get \family default will always run as if the \family typewriter --no-edit \family default option is present. \layout Subsection \begin_inset LatexCommand \label{sub:link-tree} \end_inset link-tree \layout Standard In addition to the \family typewriter --no-edit \family default option, there is a \family typewriter --link-tree \family default option. It is only useful with the \family typewriter --no-edit \family default option. The \family typewriter --link-tree \family default option will use hard links when getting a tree, reducing both the space and time required. However, because it links with cached revisions, write permissions in the cache will get modified as well. This means that versioned write permissions will, in general, be unreliable. If it turns out that write permissions are not important for your project (as is often the case), then \family typewriter --link-tree \family default could well be a useful option. Like \family typewriter no-edit \family default , you can set the \family typewriter link-tree \family default parameter in \family typewriter arx param \family default to make hard linked trees the default. \layout Subsection Timestamps \layout Standard Another possible method that could have been used is to save timestamps of files on the initial \family typewriter get \family default . Then figuring out whether a file has changed means ArX would only have to look at the timestamp of a file. You can also compare more than just timestamps (e.g. size). This method is very popular, being used by TLA, Darcs, Subversion, CVS, and Stellation. It is a little nicer interface, since you do not have to explicitly mark a file as editable before editing. \layout Standard However, it falls down on many common filesystems. Many filesystems have a timestamp resolution of one second. That means that if you get a project tree and edit a file all within one second, then that file will not show up as changed. Normally, people can not type that fast, so it is not a problem. However, if you are using some kind of automatic patch robot (as in section \begin_inset LatexCommand \ref{sub:Multiple-commiters-(a} \end_inset ), then the robot will create a project tree and apply the patch. Some changes to files may then be committed, and others not. In general, any kind of scripted use can cause these problems. \layout Standard These problems are not academic. All of the aforementioned version control systems have had problems arising from these inexact timestamps. Darcs even has an \family typewriter --ignore-times \family default option, which is great if you remember to use it. Because of this inherent unreliability, ArX does not implement this method. \layout Section Cryptographic Checksums and Signatures \layout Subsection Theory \layout Standard Once data is stored in an archive, it may become modified or corrupted. These modifications could be accidental (e.g. disk corruption) or intentional (e.g. someone trying to insert malicious code). \layout Standard To detect these modifications, the first thing that ArX uses is checksums. There are two kinds of entities that get checksums in ArX: patches and revisions. A revision is just a complete source tree, and a patch is what gets you from one revision to another. Patches are simply tar'd, gzip'd file trees, and gzip has its own checksum. Revision checksums are more complicated. \layout Standard Whenever ArX stores a revision in the archive, it creates a manifest file. The manifest file lists each path in the revision, its properties (set with \family typewriter arx property \family default ), and a cryptographic checksum \begin_inset Foot collapsed true \layout Standard ArX uses SHA-256 for its cryptographic checksum. This checksum has no known weaknesses (as opposed to MD5 or SHA-1), and should be sufficient for the next 50 years or so. \end_inset of the path's contents. ArX then computes a cryptographic checksum of the entire manifest, and stores that into the archive. When someone downloads a particular revision, ArX recreates the manifest file based on what it has downloaded. ArX then checks the checksum of the newly created manifest file against the checksum in the archive. All of this is completely automatic, and you won't notice it unless something goes wrong. \layout Standard However, while this may work great for catching errors due to corrupted hard drives and bad memory, it won't stop someone from deliberately inserting malicious code into the archive. They can always replace the checksum while replacing the original patch. To solve this, ArX uses cryptographic signatures. \layout Standard Once again, both revisions and patches can be signed. Patches are signed directly by storing a detached signature of the patch file in the archive. Revisions are signed indirectly by storing a detached signature of the revision checksum in the archive. In addition, ArX stores in the archive a list of cryptographic keys that are allowed to sign revisions in that archive. \layout Standard So the first time a person downloads a revision or patch from a particular archive, ArX will download the list of cryptographic keys. ArX will then download the actual revision or patch and check to make sure that it is properly signed by someone in that list. \layout Standard ArX uses Gnu Privacy Guard (gpg) to do the actual creation and verification of signatures. This has an advantage over other types of signatures (e.g. X.509) in that a number of people already have a gpg key. An X.509 certificate would just be another secret to protect, another password to remember, etc. In addition, your gpg public key may be already be known to the recipient. \layout Standard For those of you already using gpg, ArX does not use the usual web of trust. If you want to download a revision from a random place on the web, you don't want to have to extend your trust for other things to this particular public key. Moreover, if someone manages to compromise one person's key, they may be able to subvert a larger number of projects. However, this does mean that you should verify the public keys you download. \layout Standard It should also be noted that, while ArX uses SHA-256, gpg may internally use something weaker (e.g MD5 or SHA-1). If you are concerned, you should consult the gpg documentation to make sure you are using a secure hash. \layout Subsection Practice \layout Standard As noted before, you do not need to do anything for ArX to support checksums. ArX will automatically create and validate all checksums and let you know if there are any problems. \layout Standard To verify signatures of signed archives, you only need to have compiled ArX with gpg support. ArX will automatically download public keys, and download and verify signatures. You can use \family typewriter arx archives \family default to see what public keys are associated with an archive and verify that the keys are genuine. You can quickly verify the signatures for all of the revisions in a branch with the \family sans sig \family default command \layout LyX-Code arx sig dcoyote@example.orc/hello \layout Standard To sign your own archives is where you have to do some work. Signatures are managed on a per-archive basis. Either everything in the archive is signed, or nothing is. To create an archive that will be signed, use the \family typewriter --key \family default option to \family typewriter make-archive \family default . For example \layout LyX-Code arx make-archive --key dcoyote@example.org \backslash \layout LyX-Code dcoyote@example.org--archive archive \layout Standard The argument to \family typewriter --key \family default can also be a gpg fingerprint. If you want every archive you create to be signed, then use \family typewriter arx param \family default to set the \family typewriter gpg-key \family default parameter to your gpg public key. This will also set what your default key to sign archives will be. \layout Standard Once you have a signed archive, ArX will ask for your gpg passphrase each time you commit. This means that you will have to type in a passphrase twice each time you commit: once for the patch and once for the revision. That can quickly get tedious. So you can tell ArX to use a program such as quintuple-agent to store your password. For quintuple-agent, that would be \layout LyX-Code arx param gpg agpg \layout Standard Now ArX will use \family typewriter agpg \family default when trying to sign and verify revisions. Quintuple-agent also requires you to set up an agent, which you will have to do separately. \layout Standard If you have already created an archive and you want to make it signed, you first need to add your public key to the archive using a command like \layout LyX-Code arx sig --archive --add dcoyote@example.org--archive/ \layout Standard Then you can manually sign each patch and revision with something like \layout LyX-Code arx sig --add dcoyote@example.org--archive/hello,0 \layout Standard or just sign all the patches and revisions in a branch with \layout LyX-Code arx sig --add dcoyote@example.org--archive/hello \layout Standard If you have any mirrors, you should delete them and re-mirror. \layout Standard You can also delete a signature with the \family typewriter --delete \family default option. All of these examples will add or remove your default gpg public key set with \family typewriter arx param \family default . To add or delete a different key, use the \family typewriter --key \family default option. \layout Standard Finally, you need to let everyone else know that your archive is now signed. Other people accessing the archive will not automatically update the list of keys to trust. So if you try to sign revisions with the new key, they will not validate the signature. They must unregister and reregister the archive. \layout Section Internationalization \layout Standard ArX takes a laissez-faire attitude to internationalization. In particular, ArX treats everything as a sequence of bytes, and does not attempt to convert anything into a canonical form (e.g. UTF-8). So file contents can be in any encoding, and ArX will not care. If Gnu diff thinks that a file is binary, then ArX will use a binary diff and patch. This prevents automatic merging, but otherwise everything will work fine. Moreover, ArX does not do any line-ending conversions for Windows and Unix clients. \layout Standard The situation with file and directory names is more complex. ArX uses C Posix API's such as stat() which require null terminated strings. So if your file names have any embedded nulls, you will quickly run into problems. What this means is that if you use UTF-8 everywhere, then you should have no problems. With the various Latin encodings, all of the files will be stored correctly, but they may not display correctly if someone has a different locale. \layout Standard No guarantees are made for other encodings. In particular, Shift-JIS, Big5, VISCII, and KOI8 will probably have problems. Those encodings use the slash \begin_inset Quotes eld \end_inset / \begin_inset Quotes erd \end_inset character in a multibyte character, which will make ArX think that the path is referencing a subdirectory. \layout Section Including one project within another \layout Standard Suppose you have projects foo and bar, and you want to merge project bar into foo. That is, you want all of the files in bar to be present in foo. All you need to do is move all of the files in bar into foo with \begin_inset Quotes erd \end_inset \family typewriter arx mv \family default \begin_inset Quotes erd \end_inset . Then you just syncronize the foo tree with bar with \family typewriter history --add \family default and then commit. All of the history will be preserved, even if patches are applied from the old project. \layout Section Project Tree Inventories \layout Subsection \begin_inset LatexCommand \label{sub:Inventory-Tags} \end_inset Inventory Ids \layout Standard When ArX is looking at a path, ArX wants to assign the path a unique identity that will persist even when the path is renamed. ArX does this with inventory ids. An inventory id is just an alternate name for a path. When a path is first introduced to ArX with \begin_inset Quotes eld \end_inset \family typewriter arx add \family default \begin_inset Quotes erd \end_inset , it will have an inventory id associated with it. \layout Standard Inventory ids are contained inside a small file inside the \family typewriter _arx \family default directory which you should never deal directly with. When you need to move or delete the path associated with the external inventory id file, you must use \begin_inset Quotes eld \end_inset \family typewriter arx mv \family default \begin_inset Quotes erd \end_inset and \begin_inset Quotes eld \end_inset \family typewriter arx rm \family default \begin_inset Quotes erd \end_inset . Otherwise ArX will get confused. \layout Standard If you do not explicitly add a path, then it will not get archived. \family typewriter tree-lint \family default and \family typewriter inventory \family default come in handy here. If you do not use ArX to move and delete paths, then ArX will notice when you try to commit and force you to fix it. \layout Subsection Inventory Types \layout Standard When ArX looks at a project tree, it likes to divide the paths into various types. There are five different types: \series bold nested_tree \series default , \series bold source \series default , \series bold control \series default , \series bold ignored \series default , and \series bold unrecognized \series default . A \series bold nested_tree \series default is merely a project tree within a project tree. The other types require more explanation. \layout Standard These types come about because ArX has some decisions to make when looking at a file. ArX has to decide whether a file will get stored into an archive. Files classified as \series bold source \series default or \series bold control \series default are stored in the archive, everything else will not be. The only difference between \series bold source \series default and \series bold control \series default is that you created the \series bold source \series default paths, while ArX created the \series bold control \series default paths. For files that are not being archived, ArX has to know whether it should warn the user during \family typewriter tree-lint \family default . Only \series bold unrecognized \series default files trigger warnings just by being classified as \series bold unrecognized \series default . This is summarized in Table \begin_inset LatexCommand \ref{Categories table} \end_inset . \layout Standard \begin_inset Float table wide false collapsed false \layout Standard \begin_inset Tabular \begin_inset Text \layout Standard Type \end_inset \begin_inset Text \layout Standard Stored in Archive? \end_inset \begin_inset Text \layout Standard Created by \end_inset \begin_inset Text \layout Standard tree-lint warning? \end_inset \begin_inset Text \layout Standard source \end_inset \begin_inset Text \layout Standard Yes \end_inset \begin_inset Text \layout Standard User \end_inset \begin_inset Text \layout Standard No \end_inset \begin_inset Text \layout Standard control \end_inset \begin_inset Text \layout Standard Yes \end_inset \begin_inset Text \layout Standard ArX \end_inset \begin_inset Text \layout Standard No \end_inset \begin_inset Text \layout Standard ignored \end_inset \begin_inset Text \layout Standard No \end_inset \begin_inset Text \layout Standard User \end_inset \begin_inset Text \layout Standard No \end_inset \begin_inset Text \layout Standard unrecognized \end_inset \begin_inset Text \layout Standard No \end_inset \begin_inset Text \layout Standard User/ArX \end_inset \begin_inset Text \layout Standard Yes \end_inset \end_inset \layout Caption \begin_inset LatexCommand \label{Categories table} \end_inset Inventory Types \end_inset \layout Standard The algorithm that ArX uses to classify a path is: \layout Enumerate If the path is a directory and has an \family typewriter _arx \family default subdirectory, then it is a \series bold nested_tree \series default . \layout Enumerate If the path is in the \family typewriter _arx \family default directory, then it is \series bold control \series default . \layout Enumerate If the path has an inventory id, then it is \series bold source \series default . \layout Enumerate If the path's name matches with the regex for \series bold ignore \series default , then it is \series bold ignore \series default . \layout Enumerate Otherwise, it is \series bold unrecognized \series default . \layout Standard \begin_inset Quotes eld \end_inset \family typewriter arx inventory \family default \begin_inset Quotes erd \end_inset will print out a list of all of the paths and how they have been classified. By default, \family typewriter inventory \family default will not print out the \series bold control \series default paths. The default regex for \series bold ignore \series default is empty. You can change it with \begin_inset Quotes eld \end_inset \family typewriter arx ignore \family default \begin_inset Quotes erd \end_inset . For example, to change the ignore regex to ignore files ending with \family typewriter .o \family default , \family typewriter .bak \family default , or \family typewriter ~ \family default , the command would be \layout LyX-Code arx ignore "^.*(.o|.bak|~)$" \layout Standard ArX uses Boost.Regex, which uses the regular expression syntax described in ECMA-262, ECMAScript Language Specification, Chapter 15 part 10, RegExp (Regular Expression) Objects (FWD.1). \layout Section \begin_inset LatexCommand \label{sec:Pristine-Trees} \end_inset Pristine Trees \layout Standard ArX normally stores a complete copy of the project tree in the \family typewriter _arx \family default directory. This allows commands which need to compare against a previous revision, such as \family typewriter commit \family default , \family typewriter diff \family default , \family typewriter undo \family default , and \family typewriter file-undo \family default , to complete quickly. Also, if ArX has to get a particular revision, it can use that pristine tree as a base to start from instead of having to fetch everything from the archive. \layout Standard Usually, a project tree will only have the pristine tree of the latest revision. ArX will automatically keep it up to date for you. Sometimes, you may find it useful to have pristine trees from other revisions, such as revisions that have branched off of yours. You can query, add, or remove pristine trees with \family typewriter tree-cache \family default . \layout Standard One problem with pristine trees is that they do take up more space. See section \begin_inset LatexCommand \ref{sub:link-tree} \end_inset for one strategy for ameliorating that. \layout Section Additional Tools \layout Standard Included with the ArX distribution are a few additional tools. \layout Itemize A bash completion code to make typing many of the commands less onerous. \layout Itemize An emacs mode which integrates ArX into the editor. \layout Itemize A python script \family typewriter check_moved.py \family default which is useful when importing patches from non-ArX users. A diff can simulate a file rename by deleting and re-adding the file. \family typewriter check_moved.py \family default will detect that and fix up the internals of ArX to correctly track that move. \layout Itemize A patch-queue manager \family typewriter pqm \family default . See Section \begin_inset LatexCommand \ref{sub:Multiple-commiters-(a} \end_inset . \layout Chapter Beyond this manual \layout Standard This manual has presented most of the commands available. If you want to find out what all of the command's are, \layout LyX-Code arx --help-commands \layout Standard will print them out. By necessity, this manual has not plumbed all of the various options to the commands. All of the commands have a help screen that can be accessed with the --help command. \layout Chapter \start_of_appendix Patch Algorithm \layout Standard There are three possible relations between two objects: parent (p), child (c), and other (o). A parent is a parent directory, child is a child directory, and other is something that is not in the same hierarchy. Viewed this way, there are nine different possible ways to move things: \layout Enumerate p->p \layout Enumerate p->c \layout Enumerate p->o \layout Enumerate c->p \layout Enumerate c->c \layout Enumerate c->o \layout Enumerate o->p \layout Enumerate o->c \layout Enumerate o->o \layout Standard We also want things that are in a directory that is being renamed or deleted to be automatically renamed or deleted if they are not otherwise specified. \layout Standard If someone doesn't want things to be automatically deleted, then we can only delete directories that are already empty, because the contents have all been eliminated. \layout Standard The basic algorithm is: \layout Enumerate Get a list of all renames and deletes, and sort it so that the bottom-most elements are first. That is, if we have \newline \family typewriter a/ \newline a/b/ \newline a/c/ \newline a/d/ \newline a/b/c \newline a/c/c \family default \newline Then it should get sorted as something like \newline \family typewriter a/d/ \newline a/c/c \newline a/c \newline a/b/c \newline a/b \newline a/ \family default \newline Note that this is both renames and deletes. For example, \family typewriter a/c \family default might be deleted and \family typewriter a/c/c \family default might be renamed. \layout Enumerate In this bottom-up ordering, we rename the deleted files to \family typewriter ,,delete-0 \family default , \family typewriter ,,delete-1 \family default , ... and renamed files to \family typewriter ,,renamed-0 \family default , \family typewriter ,,renamed-1 \family default , ... in the temp directory. If a source does not exist, complain and put a note somewhere. \layout Enumerate Figure out where a path should go. If the path is just being renamed (foo/a -> foo/b) as opposed to being moved (foo/a -> bar/a), then just rename the path regardless of its current parent. If it is just being moved, then move the path, regardless of its current name. Note that ArX knows if a parent directory has been moved and puts the path in the right place. If the destination parent does not exist, signal a conflict and put the path in the destination given by the patch. \layout Enumerate Sort the destinations of the renames in a top-most fashion (opposite of bottom-up). Move the renames into their destination using this ordering. If the destination exists, rename the destination to (original_name).orig. If _that_ exists, then we try .orig-1, .orig-2, ... \layout Enumerate If we are removing deletes, then just delete all of the ,,delete objects. If we are keeping them, then do a similar rename for the \family typewriter ,,delete-* \family default files, moving things to a \family typewriter ,,removed-by-dopatch \family default directory but it has the original name. There should be no conflicts when doing this rename. \layout Enumerate Delete the temporary directory. There should be nothing in it. \layout Enumerate Apply regular and metadata patches to paths. \layout Chapter Conflicts \begin_inset LatexCommand \label{cha:Conflicts} \end_inset \layout Standard There are 12 different types of possible conflicts. Most of these types are related to moving and renaming paths. One thing to keep in mind is that ArX handles renames ( \family typewriter foo/a -> foo/b \family default ) separately from moves ( \family typewriter foo/a -> bar/a \family default ). So there can be conflicts related to the parent directories separately from the renamed path. \layout Enumerate Merge: There was a conflict when applying a three-way merge to a file. This is the most common type of conflict when merging files, where two people make conflicting changes to a single file. ArX prints out the locations of the partially merged file, the original version in the tree, the ancestor's version, and the sibling's version. For example, ArX might print out \newline \newline \family typewriter foo foo.tree foo.ancestor foo.sibling \newline \newline \family default If a merge script exists (see Appendix \begin_inset LatexCommand \ref{sec:Three-way-merges} \end_inset ), ArX will invoke the script for these files. \layout Enumerate Patch: There was a conflict when applying a patch to a file. This is the most common type of conflict when using \family typewriter replay \family default or the \family typewriter patch \family default algorithm in \family typewriter merge \family default , where two people make differing changes to the same file. ArX prints out the locations of the file with perhaps some parts of the patch applied, a copy of the file before it was patched, and a copy of the rejected hunks of the patch. For example, it might print out \newline \newline \family typewriter foo foo.orig foo.rej \newline \family default \newline If a patch-merge script exists (see Appendix \begin_inset LatexCommand \ref{sec:Patch-merges} \end_inset ), then ArX will invoke the script on these files. \layout Enumerate xdelta: There was a conflict when applying a patch to a binary file. ArX uses the xdelta algorithm to compute diffs between binary files, and patches to binary files only work if the file is exactly what is expected. So there is no fuzz factor to allow for modified files to be patched. ArX prints out the name of the file and the rejected xdelta patch. For example, it might print out \newline \newline \family typewriter foo foo.xdelta \family default \newline \newline Unfortunately, there is not much that you can do with \family typewriter .xdelta \family default files. They use a different format than the xdelta program. \layout Enumerate Move Target: The destination of a rename is already occupied. For example, if the patch renames \family typewriter foo \family default to \family typewriter bar \family default , and \family typewriter bar \family default already exists. ArX prints out the contended name and where the original has been moved. In this example, ArX would print out \newline \newline \family typewriter bar bar.orig \layout Enumerate Move Parent: The parent of a path that has been renamed has been changed in some incompatible manner. For example, if a patch renames \family typewriter foo/a \family default to \family typewriter bar/a \family default , but the file is in directory \family typewriter baz \family default . ArX prints out the initial placement of the moved path, the patches initial parent directory, and the patches destination parent directory. In this case, ArX would print out \newline \newline \family typewriter baz/a foo => bar \layout Enumerate Rename: The name of a path has been changed in some incompatible manner. For example, if a patch renames \family typewriter foo/a \family default to \family typewriter foo/b \family default , but the file is already named \family typewriter foo/c \family default . ArX prints out the initial location of the moved path, the patches initial location of the moved path, and the patches destination of the moved path. In this case, ArX would print out \newline \newline \family typewriter foo/c foo/a => foo/b \layout Enumerate Deleted Parent: The parent directory for the destination of a move has been deleted by this patch. For example, suppose the patch moves \family typewriter foo/a -> bar/a \family default and deletes the directory \family typewriter baz \family default , but \family typewriter bar \family default has been moved into a subdirectory of \family typewriter baz \family default . ArX prints out the patches initial and final destination. In this case, ArX prints out \newline \newline \family typewriter foo/a => bar/a \layout Enumerate No Parent: The parent directory for the destination of a move path has been deleted outside of this patch. For example, if the patch moves \family typewriter foo/a \family default to \family typewriter bar/a \family default , but \family typewriter bar \family default was deleted before the patch was applied. This differs from a Deleted Parent conflict where the parent directory is deleted in the patch itself. ArX prints out the patches initial and final destination. In this case, ArX prints out \newline \newline \family typewriter foo/a => bar/a \layout Enumerate Missing Moves: A path that is being moved seems to be missing. ArX will print out the patches initial and destination location, and the path's inventory id. For example, it might print out \newline \newline \family typewriter foo bar 32472534872abd896dc986de22f87de9fef997a97cbd97e9779824234827648d \layout Enumerate Missing Patches: A path that is being patch seems to be missing. ArX will print out the patches path location. \layout Enumerate Add: A path is being added with the same inventory id. For example, you might have a path \family typewriter foo \family default with the inventory id \family typewriter a9de... \family default , and you are trying to add a path \family typewriter bar \family default with the same inventory id. ArX will print the path you are trying to add, the path that conflicts with it, and the inventory id. For this example, ArX will print out \newline \newline \family typewriter bar foo a9de... \family default \newline \newline Note that ArX will only signal a conflict if either the name or the content of the path is different. So if you apply an ArX patch and then immediately reapply it, you should not get any of these kinds of conflicts. \layout Enumerate Directory Loop: ArX encountered a loop when trying to move a path. This conflict happens when the patch tries to move a directory to its own subdirectory. For example, suppose the patch moves \family typewriter foo -> bar/foo \family default , but the tree already has \family typewriter foo/bar \family default . If ArX detects a directory loop, ArX will try to move everything back to where it was before. This may cause additional conflicts if some parent directories are deleted. ArX will print out the paths current location and the patch's initial and destination locations. For this example, ArX will print out \newline \newline \family typewriter foo foo -> foo/bar/foo \family default \newline \family typewriter foo/bar bar/foo -> bar/foo/bar/foo \family default \newline \newline Note that ArX inferred the move of \family typewriter foo/bar -> bar/foo/bar/foo \family default . \layout Chapter Sample Merge Scripts \begin_inset LatexCommand \label{cha:Sample-Merge-Scripts} \end_inset \layout Section Three way merges \begin_inset LatexCommand \label{sec:Three-way-merges} \end_inset \layout Standard ArX looks in ~/.arx/merge3 for an executable merge script. The script is given four arguments \layout Enumerate The original tree file \layout Enumerate The ancestor file \layout Enumerate The sibling file \layout Enumerate The destination tree file \layout Subsection Meld \layout LyX-Code rm \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \layout LyX-Code mv \begin_inset Quotes eld \end_inset $1 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \layout LyX-Code meld \begin_inset Quotes eld \end_inset $2 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $3 \begin_inset Quotes erd \end_inset \layout Subsection Xxdiff \layout LyX-Code rm \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \layout LyX-Code xxdiff --title1 ancestor --title2 tree --title3 sibling -M \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset --show-merged-pane \begin_inset Quotes eld \end_inset $2 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $1 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $3 \begin_inset Quotes erd \end_inset \layout Subsection kdiff3 \layout LyX-Code rm \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \layout LyX-Code kdiff3 --L1 ancestor --L2 tree --L3 sibling -o \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $2 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $1 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $3 \begin_inset Quotes erd \end_inset \layout Subsection gvimdiff \layout LyX-Code rm \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \layout LyX-Code mv \begin_inset Quotes eld \end_inset $1 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \layout LyX-Code gvimdiff \begin_inset Quotes eld \end_inset $2 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \begin_inset Quotes eld \end_inset $3 \begin_inset Quotes erd \end_inset \layout Subsection X/Emacs \layout LyX-Code rm \begin_inset Quotes eld \end_inset $4 \begin_inset Quotes erd \end_inset \layout LyX-Code emacs --eval \begin_inset Quotes eld \end_inset (ediff-merge-files-with-ancestor \backslash \begin_inset Quotes erd \end_inset $1 \backslash \begin_inset Quotes erd \end_inset \backslash \begin_inset Quotes erd \end_inset $3 \backslash \begin_inset Quotes erd \end_inset \backslash \begin_inset Quotes erd \end_inset $2 \backslash \begin_inset Quotes erd \end_inset nil \backslash \begin_inset Quotes erd \end_inset $4 \backslash \begin_inset Quotes erd \end_inset ) \begin_inset Quotes erd \end_inset \layout Section Patch merges \begin_inset LatexCommand \label{sec:Patch-merges} \end_inset \layout Standard ArX looks in ~/.arx/patch-merge for an executable merge script. The script is given three arguments \layout Enumerate The original tree file \layout Enumerate The .rej file \layout Enumerate The .orig file \layout Standard At present, the only tool that works well with .rej files is X/Emacs. The script for X/Emacs is simply \layout LyX-Code emacs $2 \layout Standard The following is a recipe from Miles Bader for using emacs \layout Quote If you're using an up-to-date version of emacs (I mean the original GNU Emacs, I'm not sure about xemacs), it should enter diff-mode automatically when you visit the .rej file. From there, there are several useful commands you can use, for instance, putting the cursor in a diff `hunk', and pressing `C-c C-c' will attempt to jump to the corresponding location in the source file; typing `C-c C-a' while in a hunk will try to actually apply the hunk (and will fail if it can't). Applying a hunk from diff-mode sometimes succeeds where patch failed, though I'm not exactly sure why, as it's actually more strict about matching the original file (it doesn't do `fuzzy' application). \layout Quote So for instance a typical strategy I'll use is: \layout Quote (1) Visit the .rej file in emacs; this will automatically be in diff-mode \layout Quote (2) Make the buffer writable so I can modify the .rej file; this is just my personal style, you don't have to do this. diff-mode by default makes the buffer read-only, but I like to delete each hunk successfully applied, to make bookkeeping easier for big .rej files. \layout Quote (3) Use the command `M-U' first, which converts the .rej file into `unified diff' format, which I find easier to read; again this is not necessary though, just something I like (and of course the buffer must be writable from step (2) to do this!). \layout Quote For each hunk: \layout Quote (3) Use C-c C-a to try to apply the hunk; if application succeeds, delete the hunk from the .rej file with `M-d' (.rej buffer must be writable to do this), and go on to next hunk, otherwise: \layout Quote (4) Use C-c C-c to find the source location -- this command will use line numbers as a backup strategy, so it usually gets you at least close -- and see if there's some obvious problem where the source file has change from what the patch is expecting. \layout Quote (5) If there's an obvious difference, say added code in the hunk's context lines, _modify the hunk_ to match the source, making sure any new lines you add to the hunk include appropriate diff line-start characters (' ', '+', '-'). diff-mode will automatically make sure that the hunk line counts etc are kept up-to-date. Of course this requires care, but I find it easier to think about the interacti on of changes if I keep the source file unchanged and update the hunk. If the hunk then applies, then delete it and contine as in step (3). \layout Quote (6) Sometimes diff generates really big hunks, which include many individual changes, and are difficult to think about as a whole. For these, I often use the diff-mode `C-c C-s' command, to split the current hunk into two smaller hunks at the current line (this only works in unified diff format, for obvious reasons), and then deal with each smaller hunk individually. Sometimes, if you're not sure where the problem in a big hunk is, you can use C-c C-s to do a binary search for the mismatch point (and use emacs' undo command to undo any split that's not useful). \layout Quote The above might sound a bit complicated, but really it's not to bad once you know the diff-mode commands. \layout Quote The crucial thing I think, is that it's _much_ easier to handle non-trivial conflicts with proper .rej files, compared to CVS conflict markers. the main reason I think, is that patch is more conservative, and requires a certain amount of surrounding context to match for a patch to be applied, and includes the failing context in the .rej files so you can see what happened. Together with diff's habit of merging adjacent hunks into bigger hunks, this means that potentially problematic merges are more likely to simply fail -- which is a _good_ thing... \layout Quote CVS requires _no context_, and though this can be convenient for `obvious' cases, by the time that you realize something is non-obvious, it's already too late, CVS has already applied a bunch of possibly incorrect changes, intermixed with non-applied changes using context markers. \layout Quote -Miles \layout Chapter* Glossary \layout Description archive A directory where revisions are stored. See Section \begin_inset LatexCommand \ref{sec:Archives} \end_inset \layout Description branch A specific line of development. See Section \begin_inset LatexCommand \ref{sub:Branches and Revisions} \end_inset \layout Description inventory\SpecialChar ~ id A unique name for a path that persists across renames. See Section \begin_inset LatexCommand \ref{sub:Inventory-Tags} \end_inset \layout Description path A file or directory. In many case, ArX treats files and directories in very similar ways. \layout Description project A collection of all of the various branches and revisions that make up a particular work. \layout Description project\SpecialChar ~ tree A directory that contains a working copy of your work. \layout Description pristine A protected, unaltered copy of a particular revision, normally stored in a project tree in the {arch} subdirectory. See Section \begin_inset LatexCommand \ref{sec:Pristine-Trees} \end_inset \layout Description revision A snapshot of the work at a particular time, complete with a patch log describing how it differs from previous revisions. See Section \begin_inset LatexCommand \ref{sub:Branches and Revisions} \end_inset \layout Description whole-tree\SpecialChar ~ commits A commit that involves all of the files in a project tree. \the_end