Basic

Initial import of existing project without version control

If you have a very large project, you may not want to import the entire project in one record, as that will create a very large patch file. Darcs' performance has improved greatly, so for most projects the initial commit will not be a problem. If your codebase is larger than 50MB or so, you may want to start your repository out by adding a few directories at a time. Large repositories are quite managable as long as individual patches are small.

Before adding a huge directory to darcs, use "darcs add --dry-run -r .". That way, if you see a bunch of files that you want to be 'boring', you can update _darcs/prefs/boring before you actually add the files to darcs management. This is especially useful because there is currently no "darcs remove -r" to undo the action, and trying 'darcs revert -a' in this case may delete the files! If you do botch an import by adding way to many files, the easiest thing to do is to remove the _darcs directory try again (but you may want to first backup _darcs/prefs/boring if you modified it).

Here is a handy bash alias to quickly import an existing project. This can even be used to produce quick patches and easily produce unified diffs.

alias darcsify="darcs init && darcs add \$(darcs whatsnew -ls | awk '/^a\ / {print \$2}') && darcs record -a -m'Initial import'"

darcs remove

First of all, don't forget that if you do rm -rf directory_in_question darcs will automatically detect the remove.

Still, if you want to recursively darcs remove a directory without actually getting rid of it in your darcs directory

darcs show files | grep directory_in_question | xargs darcs remove

If you accidentally 'darcs remove' a file you can do a 'darcs add' to the same file and it will essentially undo the erroneous remove.

Undeleting an accidentally removed file

When you need to undelete a file you accidentally deleted you can call

darcs revert -a [file or dir]

The -a is to answer yes to all the patches since obviously a half restored file wouldn't do you much good.

Tips easily excluding the _darcs directory when searching

With the zsh shell:

  1. Use zsh if you are using other shells.

  2. setopt extendedglob

  3. grep -R ^_darcs -- The more general case would be  <glob_to_include>~<glob_to_exclude> 

With the bash shell

  1. shopt -s extglob to turn on extended globbing syntax.

  2. grep -R string !(_darcs) to cause the shell to skip the glob that matches _darcs.

You might also wish to use an alias or script to make this even easier. Here are a couple options:

An alias for your .bash_profile

alias dgrep="find . -path '*/_darcs' -prune -o -print0 | xargs -0 egrep"

then you can just use dgrep string.

A script for your ~/bin directory, which includes a customizeable "prune" list, to ignore other things as well:

an rgrep script

#!/usr/bin/perl -w
# originally by Michael Schwern
# Like grep -r except...
# * you can leave off the directory and it will use . instead of waiting like
# a dumbshit for STDIN
# * It handles paths with spaces and quotes.
# * it will not traverse into these directories or files.
my @Prunes = (qw(.svn CVS blib *~ *.bak _darcs), '#*');
my @Args = @ARGV;
my $Dir;
if( grep(!/^-/, @Args) <= 1 ) {
    $Dir = '.';
}
else {
    $Dir = pop @Args;
}
@Args = map { "'$_'" }
        map { s/'/'"'"'/g; $_ } @Args;
# Escape spaces and quotes
$Dir =~ s{([ '"])}{\\$1}g;
my $prunes = join ' -o ', map { "-name '$_' -prune" } @Prunes;
exec "find $Dir $prunes -o -type f -print0 | ".
     "xargs -0 grep @Args";

how to get a bunch of tar balls (different revisions of same software) into a darcs repo

The best way is to use darcs_load_dirs. This program is designed specifically for this purpose. It will not only handle changes, adds, and removes, but also has a way to prompt the operator to help with renames.

Get it with:

(Yes, that is the correct URL; the tool started life as an Arch tool, and this repo provides both tla_load_dirs and darcs_load_dirs)

The manual method:

you got different versions of the software in tarballs, now to get them into a darcs repo, follow these steps:

  1. untar first version of tarball into vc/sw
  2. darcs init, add and record
  3. mv _darcs into a different dir (/tmp)
  4. rm -rf vc/sw/*
  5. mv _darcs back to vc/sw
  6. untar second version of tarball into vc/sw
  7. darcs record
  8. go to step 3

another version of this idea suggested was moving _darcs to another dir and a ln -s everytime instead of a rm and mv (steps 4 & 5)

How to get darcs to not be so trigger-happy with its prompts

A question came up in the IRC channel early one day on how to configure or trick darcs into not using "hot" prompts -- that is, prompts which are line-fed, not character fed. In still other words, prompts where the user has to hit ENTER to submit his response.

For most of the day, no answer came, and after searching the wiki, the author declared that it wasn't really possible. However, the answer came through later in the evening: simply wrap your normal darcs command, options and all, inside a pipeline surrounded by cat.

For example, to record changes interactively, but without the hot prompts,

cat | darcs record | cat

Now the user will be required to type ENTER to submit his selections for all prompts, including the yes/no prompts.

Advanced

GnuPG and darcs on SuSE 9.1

If running the command:

darcs send --sign

on SuSE Linux 9.1 Professional gives you the following message:

darcs failed: Error running external program 'gpg'

and you have a passphrase protected key, check to see if:

use-agent

is enabled in your ~/.gnupg/gpg.conf. If it is, either install GnuPG-Agent or disable it in your config file with

no-use-agent

I have it disabled on my setup since there seems to be no available package of GnuPG-Agent available for SuSE 9.1 -- NimrodAbing

About master and working repositories

I'm working on a project hello-world. With CVS (or Arch, for that matter), I'd set up a repository /var/cvs/ with a module hello-world/, and check out a working dir ~/hello-world/. With that setup, I can easily switch my working dir to an earlier version (or a different branch) whenever I need to.

With darcs, I might be tempted to just set up a single repository ~/hello-world/. If I do that, there is no way I can go backwards in time without actually losing my changes.

Instead, I set up a "master" repository /var/repos/hello-world/, and use a clone ~/hello-world/ as my working dir. Where I'd use cvs commit, I do darcs record followed with darcs push. In this manner, I get the same level of comfort as with cvs: I can go backwards in time (darcs unpull), go forwards in time (darcs pull), or even rm -r the working dir and get a new copy if I've made a mess of things.

The one thing missing is easily switching between branches: there's no easy way to unpull exactly the changes that are in /var/repos/hello-world/ but not in /var/repos/hello-world-stable/, a comment which more properly belongs in the WishList.

Somebody noted:

Of course, this creates a new copy rather than changing the current copy in place, which, while sometimes useful, is a different thing altogether. I've usually got one Emacs with 135 files open, a Lisp listener (interactive development environment), and a buch of xterms all set up in the working directory. Switching to the new directory would require restarting all of the above in the new directory.

Please see http://lists.osuosl.org/pipermail/darcs-users/2004-July/002351.html for more details. -- JuliuszChroboczek

Making the most of decentralisation

Everybody pulls, or how to deal with not having a central push depot.

Say you are all working on an article and you don't want to go through the trouble of setting up a central push depot, dealing with umasks and all of that boring stuff. What you really want is a lightweight solution where everybody pulls from each other. This is possible in darcs, but the question here is how do we make it <em>convenient</em>? Here are some tricks I use to make my life easier:

Keep in mind that none of these are strictly neccesary. They are just tricks I use to make things more convenient for me; and they may not be applicable for your needs.

darcs and permissions (configure)

Ideally, when somebody darcs get's your code, they should just be able to do ./configure; make; make install, but one minor annoyance is that darcs doesn't keep track of file permissions. Here is what I do to get my Makefile to chmod u+x configure for the user.

My configure script produces a preferences file called config.mk. If this file exists, I include it into my Makefile:

config_file:=config/config.mk
ifneq '$(wildcard $(config_file))' ''
include $(config_file)
endif

If the file does not exist, then the following target is run. It performs the chmod for me. Note that the target must be called from all relevant targets, for instance, install

$(config_file):
        chmod u+x configure
        @echo >&2 "Please run ./configure to setup the build system."
        @exit 1
install: $(config_file)

Notes:

darcs and autoconf/automake

If you use autoconf/automake be careful! The default autogen.sh script generated by autoconf/automake can mess up your darcs repository. By default this script looks for all the configure.in files it can find, starting in the current directory, and runs autoconf on them. This means that it will find the _darcs/current/configure.in and will autoconf it, thus corrupting your repository...

The fix is simple, look for a line in autogen.sh looking like:

for coin in `find $srcdir -path $srcdir/CVS -prune -o -name configure.in -print`

and replace it with:

for coin in `find $srcdir -path $srcdir/_darcs -prune -o -name configure.in -print`

When darcs gets wider acceptance I hope this will be included in the default automake/autoconf distrib. -- StephanePopinet

how to set up a shared writable repository without granting full ssh access or using an email gateway

Set up your repo and a group which can write to it. Something like the following, also arrange for their umask to be 002, I don't know how:

addgroup projectgroup
chgrp -R projectgroup /repos/project
chmod -R g+w /repos/project
find /repos/project -type d -exec chmod g+s {} \;

(Signed email users, you might need to restore your allowed_keys permissions after this.) Next install scponly:

Debian : apt-get install scponly
Arch Linux: pacman -S scponly
Gentoo : emerge scponly

And for each committer:

adduser --home /repos/project --no-create-home --shell /usr/bin/scponly --ingroup projectgroup username

This user will be able to push (and scp/sftp/rsync) as allowed by unix file permissions, with /repos/project as their login directory, but won't be able to execute anything. You could also use scpjailer to restrict them to the repo dir, which would be even better; I haven't tried this. Use your own judgement on how far to trust this.. --SimonMichael

grouping patches with tags in their names

darcs can in many contexts work on whole groups of patches based on their names, by means of regular expressions. You can make use of this by putting tags in the patchnames.

For example reset pointer to zero after it is freed <bugfix> <file hash>. Patches concerning the file hash code can than be listed with darcs changes -p '<file hash>' and all bugfixes can be pushed with darcs push -p '<bugfix>'. All bugfixes for the file hash can be pulled with darcs pull -p '<bugfix>.*<file hash>'. Note that the tags must always be in alphabetical order (or some other well defined order) for multi-tag regexps to work.

See SpontaneousBranches.

How to keep track of who committed which patch

When having a central branch where a select group of people can commit to (using shell access), it is often desirable to know who committed a certain patch (e.g. when the author of the patch didn't have commit access).

A first solution is by using 'darcs send' to commit to the central branch. The procmail script can then log to a file the e-mail address of the sender of the patch.

If you still prefer darcs push, you can create a wrapper around darcs on the server where the repository resides. You'll have to rename your darcs binary to darcs.bin, and create an executable script called darcs looking like this:

DARCS=/usr/bin/darcs
LOG=~/darcs.log
PARAMS=$*
NPARAMS=${PARAMS/#apply/apply -v}
if test "$PARAMS" != "$NPARAMS"; then
        ( echo "********** Apply by $USER ***********" ; echo ; \
        exec $DARCS $NPARAMS | grep -v -E "^(We |Will|diff|Applying|Finished)" ; \
        echo ) >> $LOG
else
        exec $DARCS $PARAMS
fi

This will intercept darcs apply calls, change them into darcs apply -v, and log the output, together with the executing user to the given log file. -- RemkoTroncon

Scripts

Script to improve 'darcs annotate' output

darcs-reannotate. A small Python program that converts the output of "darcs annotate" into a more readable format.

Script to apply darcs patches from Mac OS X's Mail.app

I've writen a little AppleScript that lets you apply darcs patches created via darcs send without leaving Mail.app. Find it here. --- JoseAntonioOrtegaRuiz (link updated by TomCounsell 15 Feb 2007)

darcs send with Mac OS X's Mail.app

You can configure darcs to use Mail.app to send patches.

Save this AppleScript as ~/bin/send-mail.applescript:

(* 
Running:
osascript send-mail.applescript <to> <cc> <subject> <body> <attachment> 
*)
on run argv
        
        tell application "Mail"
                
                set displayForManualSend to false
                
                set toVar to item 1 of argv
                set ccVar to item 2 of argv
                set subjectVar to item 3 of argv
                set bodyVar to item 4 of argv
                set attachVar to item 5 of argv
                
                set composeMessage to make new outgoing message
                tell composeMessage
                        make new to recipient with properties {address:toVar}
                        if length of ccVar > 0 then
                                make new cc recipient with properties {address:ccVar}
                        end if
                        set the subject to subjectVar
                        set the content to bodyVar
                        
                        tell content
                                make new attachment with properties {file name:attachVar} at after last paragraph
                        end tell
                        
                        set visible to displayForManualSend
                end tell
                
                if not displayForManualSend then
                        send composeMessage
                end if
                
        end tell
        
end run

And add this to to ~/.darcs/defaults:

send sendmail-command osascript ~/bin/send-mail.applescript "%t" "%c" "%s" "%b" "%a"

-- BjornBringert

darcs send with GMail SMTP

Python script - simple sendmail replacement that uses SMTP protocol for delivery. Tested with GMail, but should work for other services as well. Edit script to configure your smtp server, login/pass. Then execute darcs (windows variant):

darcs send -v --sendmail-command="c:\path\to\python sendmail.py """%t""" %<"

Script to provide sums of the additions and deletions in `darcs whatsnew -s`

This AWK script provides a sum of the additions and deletions in the output of darcs whatsnew -s. The output is like that on the LKML (presumably from git):

darcs whatsnew -s 2> /dev/null | awk 'BEGIN { pr = 0; a = 0; d = 0; } /^M/ { f += 1; d -= $3; a += $4; pr = 1; } END { if (pr == 1) { print f, "files changed", a, "insertions(+)", d, "deletions(-)"; } else { print "Are you sure this is a darcs repository?"; } }'

If you would like to change or extend the script for your own needs but you are not familiar with AWK, Greg Goebel has written a great tutorial.

Misc.

Another Cygwin configuration

Here is how I got Cygwin to run -- a little different than the official method

  1. Download the darcs's Windows binary and the customized sftp.zip
  2. Put the darcs.exe and the sftp.exe in $HOME/bin
  3. Download and install Putty, pscp, sftp, etc. (Don't you already have this? :) )

  4. Put this in your ~/.bashrc:

export PATH=$PATH:$HOME/bin
# the -i is in case you are using a private key
export DARCS_SCP="`cygpath -d /cygdrive/c/utils/pscp.exe` -i c:\utils\keys\private.key"
export DARCS_SFTP="`cygpath -d $HOME/bin/sftp.exe` -i c:\utils\keys\private.key"
  1. Re-start your Cygwin shell or source ~/.bashrc

Now darcs should work fine.

Configuring MacOS X to darcs send

The postfix mail server is bundled with MacOS X. On MacOS X 10.4 it is launched on demand, so using darcs send will just work (via the sendmail compatibility interface to postfix). However there are high chances that your email will be rejected by the recipient's mail server because by default, if your user name is username and your computer name is compname the sender address will be <username@compname.local> and compname.local is not a valid sender domain. To make your emails acceptable you have to rewrite the sender address. To do that :

1. Add the following line to /etc/postfix/main.cf

canonical_maps = hash:/etc/postfix/canonical

2. Add the following line to /etc/postfix/canonical

username bla@example.com

where username is your username and bla@example.com is your valid email address.

3. Rebuild

postmap /etc/postfix/canonical

Execute the command in order to rebuild the indexed file after changing the text file.

4. Run (On 10.4 you don't need to do this, postfix is launched on demand).

sudo postfix start

to start Postfix.

sudo postfix stop

to stop Postfix.

Note that bounced messages will also be reported to bla@example.com. Tested with MacOS 10.4.3, postfix 2.1.5, darcs 1.0.4.

-- DanielBünzli -- AlbertoSantini

Use command line auto completion

You can enable very useful auto completion functionality by following the instructions in ShellCompletion.

The functionality differs depending on your shell. However I have found the bash support to be excellent. It supports autocompletion of darcs commands (get, push, etc.), options and repositories (by recording the repositories you have previously used).

-- MartynLoughran


DarcsWiki: HintsAndTips (last edited 2008-03-30 13:28:42 by techtonik)