Re: [PATCH] Re: "svn diff" doesn't work correctly if a file is replaced with a symlink locally

2018-07-19 Thread Bert Huijben
For git style patches there is some magic that also allows creating
symlinks via the file mode. I think we have some test cases on that
behavior. you might be able to use this for building a regression test for
this case.

Bert

On Thu, Jul 19, 2018 at 8:51 PM, Daniel Shahaf 
wrote:

> Dmitry Pavlenko wrote on Thu, Jul 19, 2018 at 19:03:30 +0200:
> > I'm attaching a reproducing test.
> >
>
> Thanks for the test!
>
> > I'm not 100% sure that
> >
> > [
> > 'Index: %s\n' % sbox.path('iota'),
> > '===
> \n',
> > '--- %s\t(revision 1)\n' % sbox.path('iota'),
> > '+++ %s\t(working copy)\n' % sbox.path('iota'),
> > '@@ -1 +1 @@\n',
> > '-This is the file \'iota\'.\n',
> > '+link iota\n',
> > '\ No newline at end of file\n',
> > '\n',
> > 'Property changes on: iota\n',
> > '___
> \n',
> > 'Added: svn:special\n',
> > '## -0,0 +1 ##\n',
> > '+*\n',
> > '\ No newline at end of property\n',
> >   ]
> >
> > is the expected output but definitely the diff command shouldn't fail
> with
> > exit code 1 as it does now.
>
> There isn't a patch flying around that produces this output, right?
>
> In this case, I suggest that we add a regression test that simply expects
> any
> output and exit code zero — that's «run_and_verify_svn(svntest.
> verify.AnyOutput,
> [], 'diff', wc_dir)» — and add a comment reminding us to write a more
> explicit
> expectation once the issue is fixed.  This would make sure the patch start
> passing as soon as we change the behaviour, even if the expected output
> predicted is a little off.
>
> > +++ subversion/tests/cmdline/diff_tests.py(working copy)
> > @@ -5201,7 +5201,36 @@ def diff_summary_repo_wc_local_
> copy_unmodified(sbo
> >  '--old=' + sbox.ospath('iota') + '@HEAD',
> >  '--new=' + sbox.ospath('iota2'))
> >
> > +def diff_file_replaced_by_symlink(sbox):
>
> There should be an "@XFail()" decorator here, so `make test` (and
> `./diff_tests.py`) still exit 0 despite this test (X)FAILing.
>
> > +  "diff base vs working: symlink replaces a file"
> > +  sbox.build()
>
> Since this test doesn't commit, it can pass read_only=True, then build()
> would
> be cheaper.
>
> > +  svntest.actions.run_and_verify_svn([
> > +'\ No newline at end of file\n',
>
> Please don't add new instances of backslash-space; it's an
> undefined/deprecated
> syntax that generates warnings in newer Pythons.  See r1834787.
>
> Cheers,
>
> Daniel
>


Re: [PATCH] Re: "svn diff" doesn't work correctly if a file is replaced with a symlink locally

2018-07-19 Thread Daniel Shahaf
Dmitry Pavlenko wrote on Thu, Jul 19, 2018 at 19:03:30 +0200:
> I'm attaching a reproducing test.
> 

Thanks for the test!

> I'm not 100% sure that 
> 
> [
> 'Index: %s\n' % sbox.path('iota'),
> '===\n',
> '--- %s\t(revision 1)\n' % sbox.path('iota'),
> '+++ %s\t(working copy)\n' % sbox.path('iota'),
> '@@ -1 +1 @@\n',
> '-This is the file \'iota\'.\n',
> '+link iota\n',
> '\ No newline at end of file\n',
> '\n',
> 'Property changes on: iota\n',
> '___\n',
> 'Added: svn:special\n',
> '## -0,0 +1 ##\n',
> '+*\n',
> '\ No newline at end of property\n',
>   ]
> 
> is the expected output but definitely the diff command shouldn't fail with 
> exit code 1 as it does now.

There isn't a patch flying around that produces this output, right?

In this case, I suggest that we add a regression test that simply expects any
output and exit code zero — that's «run_and_verify_svn(svntest.verify.AnyOutput,
[], 'diff', wc_dir)» — and add a comment reminding us to write a more explicit
expectation once the issue is fixed.  This would make sure the patch start
passing as soon as we change the behaviour, even if the expected output
predicted is a little off.

> +++ subversion/tests/cmdline/diff_tests.py(working copy)
> @@ -5201,7 +5201,36 @@ def diff_summary_repo_wc_local_copy_unmodified(sbo
>  '--old=' + sbox.ospath('iota') + '@HEAD',
>  '--new=' + sbox.ospath('iota2'))
>  
> +def diff_file_replaced_by_symlink(sbox):

There should be an "@XFail()" decorator here, so `make test` (and
`./diff_tests.py`) still exit 0 despite this test (X)FAILing.

> +  "diff base vs working: symlink replaces a file"
> +  sbox.build()

Since this test doesn't commit, it can pass read_only=True, then build() would
be cheaper.

> +  svntest.actions.run_and_verify_svn([
> +'\ No newline at end of file\n',

Please don't add new instances of backslash-space; it's an undefined/deprecated
syntax that generates warnings in newer Pythons.  See r1834787.

Cheers,

Daniel


[PATCH] Re: Directory becomes file when applying patch

2018-07-19 Thread Dmitry Pavlenko
Hello, Julian!
I've checked that the latest trunk version skips the directory in this case 
(much better than making it a file). So I'm not sure if it is possible to turn 
it into directory addition at all.

Anyway I've created a test for the case. I'm not 100% sure in the expected 
output/disk/status of the test but from the first glance it looks ok.

The test fails because it expects a directory with a property to be created 
but it is skipped.
-- 
Dmitry Pavlenko,
TMate Software,
http://subgit.com/ - git-svn bridge

> Hello!
> When I apply Git format patch that adds a directory with properties, a file
> is added instead.
> 
> Here I provide a reproducing script and also add a file for comparison.
> 
> I think the origin of the problem in the fact that SVN patch doesn't keep
> "node kind". But a patch in "svn diff --git" format does. Here's the example
> of the patch. Notice
> 
>  a) "Property changes on: dir" and "Property changes on: file" lines;
>  b) "new file mode 10644" for file and no such line for directory;
> 
> allowing to distinguish between files and directories.
> 
> I don't know whether it's a known issue or not but I think it would be nice
> to infer "node kind" from that information and also (if this is not already
> done) by the following logic: if patch changes "dir" and "dir/someFile",
> then "dir" is probably a directory.
> 
> 
> Index: /tmp/wc/dir
> ===
> diff --git a/dir b/dir
> --- a/dir   (nonexistent)
> +++ b/dir   (working copy)
> 
> Property changes on: dir
> ___
> Added: propName
> ## -0,0 +1 ##
> +propValue
> \ No newline at end of property
> Index: /tmp/wc/file
> ===
> diff --git a/file b/file
> new file mode 10644
> 
> Property changes on: file
> ___
> Added: propName
> ## -0,0 +1 ##
> +propValue
> \ No newline at end of property
> 
> 
> 
> The reproducing script:
> 
> 
> #!/bin/sh
> 
> SVN=svn
> 
> #1. Create an empty SVN repository.
> 
> REPOSITORY_PATH="$PWD/svn.repo"
> 
> svnadmin create "$REPOSITORY_PATH"
> 
> # 2. Add a file with properties and a directory with properties to the
> repository.
> 
> WC_PATH="/tmp/wc"
> REPOSITORY_URL="file://$REPOSITORY_PATH"
> 
> $SVN co $REPOSITORY_URL $WC_PATH
> 
> touch $WC_PATH/file
> 
> $SVN add $WC_PATH/file
> $SVN mkdir $WC_PATH/dir
> 
> $SVN propset propName propValue $WC_PATH/file
> $SVN propset propName propValue $WC_PATH/dir
> 
> # 3. Create diff between repository HEAD and working copy:
> 
> PATCH_FILE=/tmp/patch
> 
> $SVN diff --git $REPOSITORY_URL $WC_PATH > $PATCH_FILE
> 
> # 4. Cleanup the working copy
> 
> $SVN revert $WC_PATH/file
> $SVN revert $WC_PATH/dir
> 
> rm $WC_PATH/file
> rmdir $WC_PATH/dir
> 
> # 5. Apply the patch back:
> 
> $SVN patch $PATCH_FILE $WC_PATH
> 
> # 6. Make sure that the file is file and that dir is directory
> 
> FILE_TYPE=`stat -c "%F" $WC_PATH/file`
> DIRECTORY_TYPE=`stat -c "%F" $WC_PATH/dir`
> 
> if [ "$FILE_TYPE" != "regular empty file" ] ; then
>   echo ""
>   echo "File is not file but $FILE_TYPE"
>   echo ""
> fi
> 
> if [ "$DIRECTORY_TYPE" != "directory" ] ; then
>   echo ""
>   echo "Dir is not directory but $DIRECTORY_TYPE"
>   echo ""
> fi

Index: subversion/tests/cmdline/patch_tests.py
===
--- subversion/tests/cmdline/patch_tests.py	(revision 1836275)
+++ subversion/tests/cmdline/patch_tests.py	(working copy)
@@ -7913,6 +7913,56 @@ def patch_empty_prop(sbox):
 
   os.chdir(was_cwd)
 
+def patch_git_empty_directory_with_prop(sbox):
+  "empty directory addition confused with file"
+  sbox.build(empty=True)
+  wc_dir = sbox.wc_dir
+
+  # This patch is generated for empty directory addition with property by version 1.10
+  git_patch = [ "Index: dir\n",
+"===\n",
+"diff --git a/dir b/dir\n",
+"--- a/dir(nonexistent)\n",
+"+++ b/dir(working copy)\n",
+"\n",
+"Property changes on: dir\n",
+"___\n",
+"Added: p\n",
+"## -0,0 +1 ##\n",
+"+v\n",
+"\ No newline at end of property\n",
+  ]
+  value = 'v'
+  
+  patch_file_path = sbox.get_tempname('my.patch')
+  svntest.main.file_write(patch_file_path, ''.join(git_patch), 'wb')
+
+  dir_path = sbox.path('dir')
+
+  expected_output = wc.State(wc_dir, {
+'dir' : Item(status='A '),
+  })
+  expected_disk = svntest.wc.State('', {})
+  expected_disk.add({'dir': Item(props={'p' : value })})
+  expected_status = svntest.wc.State(wc_

[PATCH] Re: "svn diff" doesn't work correctly if a file is replaced with a symlink locally

2018-07-19 Thread Dmitry Pavlenko
Hello again,
I'm attaching a reproducing test.

I'm not 100% sure that 

[
'Index: %s\n' % sbox.path('iota'),
'===\n',
'--- %s\t(revision 1)\n' % sbox.path('iota'),
'+++ %s\t(working copy)\n' % sbox.path('iota'),
'@@ -1 +1 @@\n',
'-This is the file \'iota\'.\n',
'+link iota\n',
'\ No newline at end of file\n',
'\n',
'Property changes on: iota\n',
'___\n',
'Added: svn:special\n',
'## -0,0 +1 ##\n',
'+*\n',
'\ No newline at end of property\n',
  ]

is the expected output but definitely the diff command shouldn't fail with 
exit code 1 as it does now.
-- 
Dmitry Pavlenko,
TMate Software,
http://subgit.com/ - git-svn bridge

On среда, 11 июля 2018 г. 16:13:06 CEST Dmitry Pavlenko wrote:
> Hello.
> The following scenario fails for me: delete a file, create a symlink with
> the same name, run "svn diff". Instead of displaying the diff, SVN tries to
> read the link content. If "NOWHERE" variable is set to the file name, the
> symlink refers to itself, showing another error.
> 
> Instead I would expect something with "-" and "+" markers. If you uncomment
> #echo "link $NOWHERE" > $WC_PATH/trunk/file
> 
> and comment out "ln -s" call, the script will display approximately what I
> would expect (but without svn:special).
> 
> I'm not sure if this is a known bug, sorry for reporting something known if
> it is.
> 
> Locally I also have similar scenario failing in another way: before reading
> the symlink it displays deletion of "trunk/trunk/symlink" (yes, unexpectedly
> double "trunk", in my local test the file is called "symlink"). But I think
> it's the same issue. If it will still fail after this one is fixed, I'll
> analyze why.
> 
> 
> 
> #!/bin/sh
> 
> SVN=svn
> 
> #1. Create an empty SVN repository.
> 
> REPOSITORY_PATH="$PWD/svn.repo"
> 
> svnadmin create "$REPOSITORY_PATH"
> 
> # 2. Add a file to the repository.
> 
> WC_PATH="/tmp/wc"
> REPOSITORY_URL="file://$REPOSITORY_PATH"
> 
> $SVN co $REPOSITORY_URL $WC_PATH
> $SVN mkdir $WC_PATH/trunk
> 
> echo "content" > $WC_PATH/trunk/file
> 
> $SVN add $WC_PATH/trunk/file
> $SVN commit -m "A file added." $WC_PATH
> 
> # 3. Replace the file with a symlink pointing to nowhere (or to itself ---
> for another kind of error)
> 
> NOWHERE="changed/path"
> #NOWHERE="file"
> 
> rm $WC_PATH/trunk/file
> 
> ln -s $NOWHERE $WC_PATH/trunk/file
> 
> # By the way: uncomment the following line and comment out the previous one
> for comparison
> #echo "link $NOWHERE" > $WC_PATH/trunk/file
> 
> # 4. Create diff between repository HEAD and working copy:
> 
> $SVN diff --git $REPOSITORY_URL $WC_PATH
> 
> echo ""
> echo ""
> echo "-"
> echo "If you see something like"
> echo "-content"
> echo "+link $NOWHERE"
> echo "And svn:special property set to '*'"
> echo "Then consider test passed"
> echo "-"

Index: subversion/tests/cmdline/diff_tests.py
===
--- subversion/tests/cmdline/diff_tests.py	(revision 1836275)
+++ subversion/tests/cmdline/diff_tests.py	(working copy)
@@ -5201,7 +5201,36 @@ def diff_summary_repo_wc_local_copy_unmodified(sbo
 '--old=' + sbox.ospath('iota') + '@HEAD',
 '--new=' + sbox.ospath('iota2'))
 
+def diff_file_replaced_by_symlink(sbox):
+  "diff base vs working: symlink replaces a file"
+  sbox.build()
+  wc_dir = sbox.wc_dir
 
+  iota_path = sbox.ospath('iota')
+  os.remove(iota_path)
+
+  # create a symlink pointing to itself
+  # alternatively it could point to a non-existing path
+  sbox.simple_symlink('iota', 'iota')
+
+  svntest.actions.run_and_verify_svn([
+'Index: %s\n' % sbox.path('iota'),
+'===\n',
+'--- %s\t(revision 1)\n' % sbox.path('iota'),
+'+++ %s\t(working copy)\n' % sbox.path('iota'),
+'@@ -1 +1 @@\n',
+'-This is the file \'iota\'.\n',
+'+link iota\n',
+'\ No newline at end of file\n',
+'\n',
+'Property changes on: iota\n',
+'___\n',
+'Added: svn:special\n',
+'## -0,0 +1 ##\n',
+'+*\n',
+'\ No newline at end of property\n',
+  ], [], 'diff', wc_dir)
+
 
 #Run the tests
 
@@ -5300,6 +5329,7 @@ test_list = [ None,
   diff_unversioned_files_git,
   diff_summary_repo_wc_local_copy,
   diff_summary_repo_wc_local_copy_unmodified,
+  diff_file_replaced_by_symlink,
   ]
 
 if __name__ == '__main__':


Re: [PATCH] can't "svn patch" working copy root if the patch is in --git format

2018-07-19 Thread Dmitry Pavlenko
Hello Julian,
Here's a failing test for "no dot" case. After removing the code as I wrote 
before the test passes.
-- 
Dmitry Pavlenko,
TMate Software,
http://subgit.com/ - git-svn bridge

> Dmitry Pavlenko wrote:
> > > ... would you mind making a regression test? ...
> > 
> > OK, I could do that, but much later, in 2 weeks maybe...
> 
> Thanks. I think we should commit your fix anyway, but better if we can also
> fix the 'svn diff' output and also add a test or two.
> 
> I am thinking two tests would make sense:
> 1. test that "svn patch" can correctly parse and apply the present form of
> input where there is no dot 2. test that the round-trip of "svn diff"
> followed by "svn patch" works
> 
> Maybe I will do some or all of that, soon, but I would love it if anyone
> else wants to take care of it before I get to it.
> 
> I have filed this issue as https://issues.apache.org/jira/browse/SVN-4763
> 
> - Julian

Index: subversion/tests/cmdline/patch_tests.py
===
--- subversion/tests/cmdline/patch_tests.py	(revision 1836275)
+++ subversion/tests/cmdline/patch_tests.py	(working copy)
@@ -7913,6 +7913,49 @@ def patch_empty_prop(sbox):
 
   os.chdir(was_cwd)
 
+def patch_git_wcroot(sbox):
+  "patch working copy root"
+  sbox.build(empty=True)
+  wc_dir = sbox.wc_dir
+
+  git_patch = [ "Index: .\n",
+"===\n",
+"diff --git a/ b/\n",
+"--- a/	(revision 0)\n",
+"+++ b/	(working copy)\n",
+"Property changes on: \n",
+"___\n",
+"Added: p\n",
+"## -0,0 +1 ##\n",
+"+v\n",
+"\ No newline at end of property\n",
+  ]
+  value = 'v'
+  
+  patch_file_path = sbox.get_tempname('my.patch')
+  svntest.main.file_write(patch_file_path, ''.join(git_patch), 'wb')
+
+  expected_output = wc.State(wc_dir, {
+'.' : Item(status=' U'),
+  })
+  expected_disk = svntest.wc.State('', {})
+  expected_disk.add({'': Item(props={'p' : value })})
+  expected_status = svntest.wc.State(wc_dir, {})
+  expected_status.add({'': Item(status=' M', wc_rev='0')})
+  expected_skip = wc.State('', { })
+  
+  svntest.actions.run_and_verify_patch(wc_dir, patch_file_path,
+   expected_output,
+   expected_disk,
+   expected_status,
+   expected_skip,
+   None, # expected err
+   True, # check-props
+   False, # dry-run
+   )
+
+  svntest.actions.check_prop('p', wc_dir, [value.encode()])
+
 
 #Run the tests
 
@@ -7998,6 +8041,7 @@ test_list = [ None,
   patch_merge,
   patch_mergeinfo_in_regular_prop_format,
   patch_empty_prop,
+  patch_git_wcroot,
 ]
 
 if __name__ == '__main__':