HintsAndTips
- Basic
- Initial import of existing project without version control
- Undeleting an accidentally removed file
- Tips easily excluding the _darcs directory when searching
- how to get a bunch of tar balls (different revisions of same software) into a darcs repo
- How to get darcs to not be so trigger-happy with its prompts
- Advanced
- GnuPG and darcs on SuSE 9.1
- About master and working repositories
- Making the most of decentralisation
- darcs and permissions (hard links)
- darcs and permissions (configure)
- how to set up a shared writable repository without granting full ssh access or using an email gateway
- grouping patches with tags in their names
- How to keep track of who committed which patch
- Scripts
- Misc.
- Tips for older versions of darcs
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 too 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'"
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:
- Use
zshif you are using other shells. setopt extendedglobgrep -R ^_darcs-- The more general case would be
<glob_to_include>~<glob_to_exclude>With thebashshell
to turn on extended globbing syntax.shopt -s extglobgrep -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:
Available from <http://software.complete.org/software/projects/show/vcs-load-dirs> as either tarballs <http://software.complete.org/software/projects/list_files/vcs-load-dirs> or from a git repository <http://software.complete.org/software/repositories/show/vcs-load-dirs>.
Available as the darcs-load-dirs Debian package: aptitude install 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:
- untar first version of tarball into vc/sw
- darcs init, add and record
- mv _darcs into a different dir (/tmp)
- rm -rf vc/sw/*
- mv _darcs back to vc/sw
- untar second version of tarball into vc/sw
- darcs record
- 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
To make darcs wait for the user to hit ENTER to submit their response, 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
Even when working alone on a project, you should not work in the repository itself, but in a copy thereof. This will allow you to quickly switch to older versions whenever you need to.
For instance, it is a good practice to have a "threshold" repository between the repository in which you actually work and the "external" repository that the world can see (if such a repository exists).
work in progress----->threshold----->world visible
Thus, while working in the "work in progress" repository, you can go backwards in time (darcs unpull), forwards in time (darcs pull), or even rm -r the working dir and get a new copy if you've messed up everything.
Moreover, you can have different "work in progress" branches in parallel, and just cd between them, and also do a recursive diff to see the total change between two of them.
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 convenient? Here are some tricks I use to make my life easier:
Create a central pull depot. Arbitrarily designate one of you to be the pull master. The pull master's job is to pull from everybody else and push changes into to pull depot (unless the pull depot is just the pull master's working directory). Everybody else pulls from the pull master (this is useful when not everybody is comfortable with darcs yet)
Make use of
--no-set-defaultflag. Darcs has a handy feature where it remembers the last repository you pull/push from, so that if you dodarcs pull /tmp/fooonce, the next time you dodarcs pull, it remembers that it should do it from/tmp/foo. The only problem is that this is not so handy if you are pulling from multiple locations:darcs push /some/really/incredibly/long/path/pull_depot darcs pull /home/alice/repo darcs pull /home/bob/repo darcs push -- WRONG! this will will push into /home/bob/repoIn order to make this work better -- in order not to forget your pull depot path is to do it like this:
darcs push /some/really/incredibly/long/path/pull_depot darcs pull --no-set-default /home/alice/repo darcs pull --no-set-default /home/bob/repo darcs pushBy using the
--no-set-defaultflag, you tell darcs not to remember the path you just provided.If pulling from everybody else also involves some very long, hard-to-remember path, the pull master could also have a separate repository for each person she is pulling from:
mkdir my_project cd my_project darcs get /some/really/incredibly/long/path/pull_depot pull_depot darcs get /some/really/long/path/alice/repo alice darcs get /another/really/long/path/bob/repo bob ... cd alice darcs pull cd .. cd bob darcs pull cd .. cd pull_depot darcs pull --no-set-default ../alice darcs pull --no-set-default ../bob darcs pushThe reason this works for me is that my partners' really long paths are harder to remember and less convenient to type than the relative path of my pull depot. So I ask darcs to remember the hard stuff, and let it forget the easy stuff. 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 (hard links)
Patch-Tag, which uses unix security for securing repos, encountered the following problem, which is perhaps shared by others. When several users share a private repo, they are all on the same linux group, and the repo has rwxs for that group.
However, darcs also has a global cache for patches (and whatever objects are under _darcs/hashed.inventory)
as described in the darcs manual -> configuring darcs -> prefs -> sources
http://darcs.net/manual/node4.html#SECTION00410000000000000000
These patches are shared across repos using hard links.
So, what happens if you have two repos, with two owners, some hashes in common? The hardlinked file objects can only belong to one group, so somebody is not going to be able to access that repo.
In practice this happened less often than one might expect, because most users had the patches cached locally after an initial pull. It did happen though.
Patch-Tag finally resolved the problem by making everything under _darcs world readable. Since the parent directory (repo root for a particular repo) is world invisible, the effect is that the hardlinked file objects are shared by everybody that should have access to them, without compromising security.
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:
- this is half copied from the darcs Makefile
- might be GNU Makefile specific
- autoconf's configure seems to produce a file called config.status. You could use that instead.
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 Apple{{{}}}Script 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"
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""" %<"
See also http://wiki.darcs.net/Msmtp
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.
- Before pulling a patch, make sure all local changes are recorded. That way if you get a conflict, you are guaranteed to be able to go back without having to untangle the conflict by hand. After you pull you can always unrecord again if you didn't really want to make a patch at that point. --GaneshSittampalam
- The _darcs directory can be moved out of tree and replaced with a symlink pointing to it. This is mainly useful for situations such as preventing accidental deletion of a repository of /etc across operating system reinstalls or importing a new version of a tree from a project that doesn't itself use darcs. --JonathanConway
Another Cygwin configuration
- Here is how I got Cygwin to run
-- a little different than http://wiki.darcs.net/WindowsConfiguration
- Download the darcs's Windows binary and the customized sftp.zip
- Put the darcs.exe and the sftp.exe in $HOME/bin
- Download and install Putty, pscp, sftp, etc. (Don't you already have this? :) )
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"Re-start your Cygwin shell or
source ~/.bashrcNow darcs should work fine.--- MikeHostetler
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 :
- Add the following line to
/etc/postfix/main.cf
canonical_maps = hash:/etc/postfix/canonical
- 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.
- Rebuild
postmap /etc/postfix/canonical
Execute the command in order to rebuild the indexed file after changing the text file.
- 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).
Tips for older versions of darcs
darcs remove (before version 2.4)
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.
In darcs 2.4 and later, you can simply do darcs remove --recursive.
