Below is a transcript that shows how long it took me to copy one directory to another using svn. All I wanted to do was copy the com subdirectory of the original/java/ directory into the customised/java/ directory. On a normal filesystem this could be achieved with cp original/java/com customised/java/.
Looking back over the transcript I see what went wrong. The problem occurred because the java subdirectory of customised was not already versioned. This must have lead to Subversion scheduling the addition of the java directory to customised in the repository. Why it then ignored the com directory and yet still continued to add it's contents to customised/java/ is anybody's guess.
So the standard Linux cp command doesn't map to the Subversion cp command - the Subversion command of:
svn cp original/java/com customised/java/
maps to the Linux command of:
cp original/java/com/* customised/java/
Anyway, here's the transcript. Following it is a description of what I did wrong (apart from not reading the documentation ;-)).
--- Start ---
bash$ ls
customised original
bash$ ls original/java
com source
bash$ ls customised/java
--- 1. First attempt ---
bash$ svn cp original/java/com customised/java/
A customised/java
bash$ svn commit
Adding code/customised/java
Committed revision 61.
bash$ ls customised/java
steph
--- Now I delete the contents of customised/java/ because it's wrong ---
bash$ svn rm customised/java/*
D customised/java/steph/file/CmsProject.java
D customised/java/steph/file/CmsManager.java
-- Snip --
bash$ svn commit
Deleting code/customised/java/steph
Committed revision 62.
bash$ pwd
/mnt/store/cal/svn/apps/cms/code
--- 2. Try the copy again, with a slightly different syntax ---
bash$ svn cp original/java customised/java
A customised/java/java
bash$ svn rm customised/java/java
svn: Use --force to override this restriction
svn: 'customised/java/java/source' is not under version control
bash$ svn status
? customised/java/java/source
A + customised/java/java
bash$ svn rm customised/java/java --force
D customised/java/java
bash$ svn status
bash$ ls
customised original
bash$ ls customised
java
bash$ ls customised/java
bash$ ls original/java
com source
--- 3. Try again ---
bash$ svn cp original/java customised
svn: Destination 'customised/java' already exists
--- 4. And again ---
bash$ svn cp original/java/* customised/java/
copy (cp): Duplicate something in working copy or repository, remembering history.
usage: copy SRC DST
SRC and DST can each be either a working copy (WC) path or URL:
WC -> WC: copy and schedule for addition (with history)
WC -> URL: immediately commit a copy of WC to URL
URL -> WC: check out URL into WC, schedule for addition
URL -> URL: complete server-side copy; used to branch & tag
Valid options:
-m [--message] arg : specify commit message ARG
-F [--file] arg : read data from file ARG
-r [--revision] arg : ARG (some commands also take ARG1:ARG2 range)
A revision argument can be one of:
NUMBER revision number
"{" DATE "}" revision at start of the date
"HEAD" latest in repository
"BASE" base rev of item's working copy
"COMMITTED" last commit at or before BASE
"PREV" revision just before COMMITTED
-q [--quiet] : print as little as possible
--username arg : specify a username ARG
--password arg : specify a password ARG
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting
--force-log : force validity of log message source
--editor-cmd arg : use ARG as external editor
--encoding arg : treat value as being in charset encoding ARG
--config-dir arg : read user configuration files from directory ARG
--- 5. And again ---
bash$ svn cp original/java/ customised/java/
A customised/java/java
--- Bloody hell ---
bash$ svn rm customised/java/*
svn: Use --force to override this restriction
svn: 'customised/java/java' has local modifications
bash$ svn rm customised/java/* --force
D customised/java/java
bash$ svn commit
--- 6. Finally ---
bash$ svn cp original/java/com/ customised/java/
A customised/java/com
bash$ svn commit
Adding code/customised/java/com
Committed revision 64.
bash$ svn cp original/java/source/ customised/java/
A customised/java/source
bash$ svn commit
Adding code/customised/java/source
Committed revision 65.
bash$
--- end ---
Here's what must have happened on the copy attempts:
- Attempted to copy something into a local directory that wasn't versioned. Subversion does odd things - it versions java but copies the wrong files into it.
- Syntax was wrong because the java directory was now versioned. Hence, command behaved as expected.
- Copy of java failed because it's already versioned. Subversion doesn't do recursive copy as expected, but instead complains.
- Tried a wildcard character, which Subversion obviously doesn't support.
- Wondered if Subversion assumes you're referencing the contents of a directory if you preceed it with a slash. It doesn't.
- Finally, resorted to referencing contents of java one by one.
The lesson of this story? - the Subversion cp command is significantly less powerful than the Linux filesystem one and I shouldn't have assumed it wasn't.

