On Sat, May 19, 2012 at 5:59 PM, Alex Siyanko <asiyanko_at_xdyne.com> wrote:
> Hello,
>
> I've stumbled upon the following Subversion client 1.7.x bug:
>
> Under certain conditions SVN silently fails to fetch external file at
> specified operative revision from repository into a working copy.
> Here is the simplest scenario:
>
> 1) I create 'file.txt' and commit it to repository 'A/trunk' directory;
> 2) then I copy entire 'A/trunk' directory to 'A/tags/1.0' using 'svn copy
> URL URL' command;
> 3) next I create 'B' directory in the repository with one empty 'import'
> subdirectory, which I want to use for importing 'A/tags/1.0/file.txt' via
> svn:externals;
> 4) to use explicit revision number in svn:externals property I run 'svn
> list A/tags/1.0/file.txt -v' command, which gives me the last revision, at
> which file.txt was modified (say, revision 1).
> 5) now I checkout 'B' into a working copy and set svn:externals property
> over 'import' subdirectory as follows: ' -r1 ^/A/tags/1.0/file.txt
> file.txt'
> 6) finally I update 'B' working copy, which should fetch file.txt into
> import directory; unfortunately, that doesn't happen - 'import' directory
> remains empty, though svn reports no errors
>
> It is important to note, that this bug is not present in any SVN 1.6.x
> client. It only manifests itself in SVN 1.7.x (up to its latest version
> 1.7.5)
> I tested it on Windows and Linux platforms using both pre-compiled version
> of svn client, which comes with TortoiseSVN, as well as svn client, compiled
> and installed from tar.
> Also I tried to use both svn:// (with svnserve of 1.6.x and 1.7.x versions)
> and file:// access methods.
> The result doesn't depend on the access method, neither it depends on the
> version of the svnserve at the backend (in case of svn:// method ), so it is
> an svn client 1.7.x issue.
>
> Here is the script to reproduce the described bug:
> ##############################################################################################################
> #!/bin/sh
>
> # You might need to adjust these lines to point to your
> # compiled-from-source Subversion binaries, if using those:
> if [ -z "$SVN" ]; then
> SVN=`which svn`
> SVNADMIN=`which svnadmin`
> fi
>
> # Use English output.
> LC_ALL=C; export LC_ALL
>
> # Select an access method. If svn://, the svnserve setup is
> # handled automagically by this script; but if http://, then
> # you'll have to configure it yourself first.
> #
> # URL=http://localhost/SOMETHING/repos
> # URL=svn://localhost/repos
> URL=file:///`pwd`/repos
>
> ${SVNADMIN} create repos
>
> echo "### Making a Greek Tree for import..."
> mkdir import-me
> mkdir import-me/A
> mkdir import-me/A/trunk
> mkdir import-me/A/tags
> mkdir import-me/B
> mkdir import-me/B/trunk
> mkdir import-me/B/trunk/import
> echo "This is the file 'file.txt'" > import-me/A/trunk/file.txt
> echo "### Done."
> echo ""
> echo "### Importing it..."
> (cd import-me; ${SVN} import -q -m "Initial import." ${URL})
> echo "### Done."
> echo ""
>
> echo "### copy A/trunk to A/tags/1.0 ###"
> ${SVN} cp ${URL}/A/trunk ${URL}/A/tags/1.0 -m 'make 1.0 release of project
> A'
> revision=`${SVN} ls ${URL}/A/tags/1.0/file.txt -v| grep -P -o '^\s+\d+' |
> grep -P -o '\d+'`
> echo "### 'A/tags/1.0/file.txt' Last Commit Revision: $revision ###"
>
> echo "### checkout B/trunk to wc ###"
> ${SVN} co ${URL}/B/trunk wc
> cd wc
>
> echo "### set svn:externals property over B/trunk/import to: ' -r$revision
> ^/A/tags/1.0/file.txt file.txt' ###"
> ${SVN} propset svn:externals " -r$revision ^/A/tags/1.0/file.txt file.txt"
> import
>
> echo "### update B/trunk working copy ###"
> ${SVN} update
>
> echo "### list updated B/trunk wc contents ###"
> ls -R
> ##############################################################################################################
>
>
> The above script renders following output:
> --------------------------------------------------------------------------------------
> ### Making a Greek Tree for import...
> ### Done.
>
> ### Importing it...
> ### Done.
>
> ### copy A/trunk to A/tags/1.0 ###
>
> Committed revision 2.
> ### 'A/tags/1.0/file.txt' Last Commit Revision: 1 ###
> ### checkout B/trunk to wc ###
> A wc/import
> Checked out revision 2.
> ### set svn:externals property over B/trunk/import to: ' -r1
> ^/A/tags/1.0/file.txt file.txt' ###
> property 'svn:externals' set on 'import'
> ### update B/trunk working copy ###
> Updating '.':
>
> Fetching external item into 'import/file.txt':
> External at revision 1.
>
> At revision 2.
> ### list updated B/trunk wc contents ###
> .:
> import
>
> ./import:
> --------------------------------------------------------------------------------------
>
> The 'wc/import' directory is empty after update, when svn 1.7.x is used.
> Again, that doesn't happen with svn 1.6.x.
Thanks for the very detailed report, with reproduction script.
However, I'm not sure if there is a bug here, and if there is, exactly
what the bug is ...
The problem is that ^/A/tags/1.0/file.txt does not yet exist in r1. It
only appears after the copy, in r2. So I think you'd need "-r2
^/A/tags/1.0/file.txt file.txt", or using peg revisions would be even
better: "^/A/tags/1.0/file.txt_at_2 file.txt"
So "externals" isn't really at fault here. Apparently the "Last
changed revision" of ^/A/tags/1.0/file.txt is r1, the last revision in
which the file has changed (not the revision of the copy). I.e. "Last
changed revision" doesn't consider copies. I _think_ that's known and
desired behavior, which has always been that way. So I'm surprised
that this did work in 1.6, like you say. Has the behavior of 'svn
status' changed here?
--
Johan
Received on 2012-05-21 12:46:02 CEST