[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: bug report: svn client 1.7.x silently fails to fetch files via svn:externals under certain conditions.

From: Alex Siyanko <asiyanko_at_xdyne.com>
Date: Thu, 24 May 2012 02:57:11 +0300

On 5/23/2012 5:15 PM, Johan Corveleyn wrote:
> On Mon, May 21, 2012 at 2:41 PM, Alex Siyanko<asiyanko_at_xdyne.com> wrote:
>> On 5/21/2012 1:45 PM, Johan Corveleyn wrote:
>>
>> 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?
>>
>>
>> Hi Johan and thank you for prompt reply. Nevertheless I don't agree with
>> your reasoning.
>> Let me give my point of view on this.
>>
>> I believe that svn:externals feature, when used with operative revision (not
>> peg revision, this is important!)
>> should work the same way as other svn commands, such as for example 'cat' or
>> 'co'.
>> In other words, when operative revision is used in svn:externals, it should
>> cross copy command boundary.
>>
>> Getting back to my example, here is the question. Why then, if I, for
>> example, run:
>>
>> svn cat -r 1 file:///`pwd`/repos/A/tags/1.0/file.txt
>>
>>
>> or
>>
>> svn co -r 1 file:///`pwd`/repos/A/tags/1.0 tags-checkout
>>
>>
>> subversion happily prints file.txt contents or downloads it to a working
>> copy.
>> This happens because it is able to cross copy command boundary. BTW, this
>> works fine both in 1.6.x and 1.7.x.
>> And this is the behavior, which is described in the Red Book "The Peg
>> Revision Algorithm" section.
>> Namely, it says:
>>
>> ----------------------------------------------------------------------------------------------------------------
>>
>> The Subversion command-line client performs the peg revision algorithm any
>> time it needs to resolve possible ambiguities in the paths and revisions
>> provided to it. Here's an example of such an invocation:
>>
>> $ svn command -r OPERATIVE-REV item_at_PEG-REV
>>
>> If OPERATIVE-REV is older than PEG-REV, the algorithm is as follows:
>>
>> Locate item in the revision identified by PEG-REV. There can be only one
>> such object.
>>
>> Trace the object's history backwards (through any possible renames) to its
>> ancestor in the revision OPERATIVE-REV.
>>
>> Perform the requested action on that ancestor, wherever it is located, or
>> whatever its name might be or might have been at that time.
>>
>> ----------------------------------------------------------------------------------------------------------------
>>
>> Please pay attention to "through any possible renames" phrase in item 2.
>>
>> So, I expect, that svn: externals rule, which uses operative revision,
>> should have identical behavior.
>> And, in fact, it does in 1.6.x. Also note, that 1.7.x "kind of has" it.
>> If you take a look at the output of the script, you'll see the following
>> lines:
>>
>> Fetching external item into 'import/file.txt':
>> External at revision 1.
>>
>> Which tells me, that file.txt has been successfully fetched - there are no
>> error messages.
>> The thing is that it didn't really happen.
>> So this looks like a definite bug to me.
>>
>> I agree, that "file:///`pwd`/repos/A/tags/1.0/file.txt" doesn't exist at
>> revision 1.
>> Therefore, if I use the rule with peg revision in place of operative:
>>
>> ^/A/tags/1.0/file.txt_at_1 file.txt
>>
>>
>> svn responds with 'path not found' message, which, of course, is expected
>> behavior.
>> But if I use operative revision, svn must cross copy command boundaries
>> according to official documentation.
>>
>> Am I right or not?
>> Please let me know your opinion.
> Sorry for the late response (I got sidetracked by other things). But I
> believe you're right. There is definitely something fishy here, or at
> least I don't know what the expected behavior should be.
>
> I see that you've filed an issue in the meantime (after confirming
> with stsp on irc). Hopefully someone can look into this a bit more in
> some not-too-distant future.
>
> For completeness of the archives, this is the issue:
>
> http://subversion.tigris.org/issues/show_bug.cgi?id=4185 (SVN client
> silently fails to fetch external file ancestor specified in
> svn:externals file definition via operative revision)
>

Hi Johan,

thank you for taking your time to look at this.
I hope your opinion will help to draw more attention from the
development team.

The thing is, that the in-house software, that I've developed on top of
SVN makes heavy use of this feature.
svn:externals definitions of described type are generated
programmatically for checking out compound working copies.
And so far I don't see any other easy way around this issue, then just
rolling back all clients back to 1.6.x.

Alex.

-- 
Alex Siyanko<br>
as_at_xdyne.com
Received on 2012-05-24 01:58:16 CEST

This is an archived mail posted to the Subversion Users mailing list.