An svn:externals dir, first checked out onto an already versioned target dir
(during update), blows away local modifications.

[[[
(pseudocode)

$ svn ls
XA/
$ svn diff
--- XA/local_file
+++ XA/local_file
 orig
+very important local mod


$ svn ps svn:externals "^/A XA" .
$ svn update
D   XA/local_file
A   XA/remote_file
svn: warning: W200000: Error handling externals definition for 'XA':
svn: warning: W155035: The specified path has an unexpected status
At revision 3.
svn: E205011: Failure occurred processing one or more externals definitions

$ svn diff XA
$ svn cat XA/local_file
cat: XA/local_file: No such file or directory
]]]

The new externals definition switches the already existing dir XA to the
external URL ^/A. Probably because of the failing consistency check and its
abort, this wipes local modifications from XA/local_file.

When producing a similar situation by changing the dir external's URL, local
mods result in proper tree conflicts: "local edit, incoming delete/replace
upon switch". So the idea is that, hopefully, once above consistency check
doesn't abort the operation in this way, the update will just continue to
flag such tree conflicts, problem solved.


But that got me thinking. It's not so easy to recover local modifications
after a conflicted switch -- ever more tree conflicts, manual labor. I would
rather error early on this situation.

Added weight: since svn:externals may come in from other people, it's not
only you who's doing an 'svn switch' in own responsibility. This potentially
messes up WCs with a simple 'svn update'.

So I'd like to abort the entire dir external update
- if there's a versioned dir already, and
- if it has local mods anywhere, and
- iff the BASE node's URL is different from the URL the dir external wants
to bring in at that path.

User can still commit / diff to the path's original URL without fuss. This
(or as always a revert -R) and a subsequent update would solve any local
update situations with dir externals.

Do you like the idea & do you think that it's reasonably easy to achieve and
backportable?


FYI, comparing to file externals:

File externals are treated a bit stricter, it seems any existing BASE node's
IS_EXTERNAL status is verified before bringing in a file external:
[[[
Fetching external item into 'xa':
svn: warning: W195017: The file external from
'file:///tmp/switch_thru_external_file.vnT/repos/a' cannot overwrite the
existing versioned item at '/tmp/switch_thru_external_file.vnT/wc/xa'
]]]

If I change a successfully created file external's URL in the svn:externals
prop and update, local mods produce a text conflict. This should probably
abort the same way as above.

~Neels
#!/usr/bin/env bash

## TO MAKE THIS RUN YOUR CUSTOM COMPILED SVN, two simple options:
## 1. Adjust your PATH to point at your custom installed location:
##      export PATH="$HOME/prefix/svn_trunk/bin:$PATH"
## OR
## 2. Uncomment the four lines below to use aliases into your
##    built source tree. The next line is the only line you should
##    need to adjust.
# SVNDIR=/path/to/built_subversion_source_tree
# function svn() { "$SVNDIR/subversion/svn/svn" "$@"; }
# function svnserve() { "$SVNDIR/subversion/svnserve/svnserve" "$@"; }
# function svnadmin() { "$SVNDIR/subversion/svnadmin/svnadmin" "$@"; }

set -e

svn --version
BASE="$(mktemp -d "/tmp/$(basename "$0").XXX")"
echo "BASE = $BASE"
REPOS="$BASE/repos"
WC="$BASE/wc"
URL="file://$REPOS"
svnadmin create "$REPOS"

svn co -q "$URL" "$WC"

set +e
set -x
cd "$WC"

## ACTUAL TEST

mkdir A
echo a > A/remote_file
svn add A

svn ci -mm
svn up

mkdir XA
echo orig > XA/local_file
svn add XA
svn ci -mm

svn info XA | grep '^URL\|^Path'

echo very important local mod >> XA/local_file
svn st XA
svn diff XA

svn up
svn ls
svn ps svn:externals "^/A XA" .
svn ci -mm
# bring in external XA
svn up

svn info XA | grep '^URL\|^Path'
svn st XA
svn diff XA
ls XA/
cat XA/local_file

# Where is the very important local mod!!


## END
set +x
echo "BASE = $BASE"

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to