On Thu, May 24, 2012 at 1:57 AM, Alex Siyanko <asiya...@xdyne.com> wrote: > On 5/23/2012 5:15 PM, Johan Corveleyn wrote: >> >> On Mon, May 21, 2012 at 2:41 PM, Alex Siyanko<asiya...@xdyne.com> wrote: >>> >>> On 5/21/2012 1:45 PM, Johan Corveleyn wrote: >>> >>> On Sat, May 19, 2012 at 5:59 PM, Alex Siyanko<asiya...@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@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@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@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.
Have you tried if the following works? -r1 ^/A/tags/1.0/file.txt@2 file.txt So using a peg revision combined with the operational revision. It that works, maybe it could be a workaround? -- Johan