Add Subversion support #567

Merged
merged 59 commits into from Jun 22, 2016

Conversation

Projects
None yet
6 participants
Contributor

tsimonq2 commented Jun 10, 2016

This adds support for Subversion and fixes bug 1543243 in Launchpad.

Can one of the admins verify this patch?

Can one of the admins verify this patch?

Member

elopio commented Jun 10, 2016

Thanks for your contribution @tsimonq2, and welcome to snapcraft!
I'll leave a note here for the rest that you have already signed the contributors agreement. Thanks for that too.

This branch is missing unit tests. Take a look at snapcraft/tests/test_sources.py for the kind of things that we require for full code coverage. Let me know if you need a hand with the tests.

+ svn:
+ plugin: make
+ source: .
+ source-type: svn
@elopio

elopio Jun 10, 2016

Member

This looks good, but it's missing that make file, and the test file. I'm not sure if it's work in progress, or you forgot to add the files to git.

@chadmiller

chadmiller Jun 10, 2016

It would be nice to test "svn:" source lines, too, and one check-out and one update.

@elopio

elopio Jun 10, 2016

Member

woohoo, Chad is here! 🎉

@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

@elopio - I'm a little confused here. the git-* and hg-* directories have almost the same contents. What is different, and if applicable, what should I put in the make file and test file?

@chadmiller - Sort of going with the comment I left for elopio, would you suggest I do it as separate parts in this snapcraft.yaml, or in separate tests, and if so, would I rename the directory from simple-svn to svn-*?

@kyrofa

kyrofa Jun 13, 2016

Member

Unless I'm mistaken, it doesn't look like source-type: svn will actually work given the code (i.e. it would need to be source-type: subversion)

@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

@kyrofa Fixed in the recent set of commits I pushed

@chadmiller

chadmiller Jun 13, 2016

@tsimonq2, I also think it makes us worry that you didn't run the test and discover the problem, which is kind of bad; or that you did run tests and this test should have run and failed but did not, which is really really bad. Please find out what the problem is, here.

@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

@chadmiller If you are talking about kyrofa's issue, I found that out already, but I forgot to update my code. My bad, but it's fixed now.

What else are you referring to if not that? Can you clarify?

@chadmiller

chadmiller Jun 13, 2016

@tsimonq2, yes, I mean that the source-type couldn't have matched anything in the test, earlier, and should have caused a test failure.

@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

@chadmiller Well like I said, I figured that out myself but I forgot to edit the code. It was a simple mistake that I'm glad was caught, and I'm thankful for that. That's all.

Now, what do I do now with this directory and this snapcraft.yaml file? See comment #4 on this line note string(if that makes any sense).

snapcraft/internal/sources.py
@@ -1,4 +1,4 @@
-# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
+#-*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
@elopio

elopio Jun 10, 2016

Member

Not a big deal, but please revert this change.

@tsimonq2

tsimonq2 Jun 10, 2016

Contributor

It was an accident, I'll revert it :)

snapcraft/internal/sources.py
@@ -383,6 +403,8 @@ def _get_source_type_from_uri(source, ignore_errors=False):
source_type = 'tar'
elif source.endswith('.zip'):
source_type = 'zip'
+ elif source.startswith('svn:'):
+ source_type = 'subversion'
@elopio

elopio Jun 10, 2016

Member

another nit, please move this case after the git one. I'm a little code order freak, and I would like that all the cvs sources are together.

Can one of the admins verify this patch?

Can one of the admins verify this patch?

tsimonq2 added some commits Jun 13, 2016

snapcraft/internal/sources.py
@@ -27,7 +27,7 @@
directory tree or a tarball or a revision control repository
('git:...').
- - source-type: git, bzr, hg, tar or zip
+ - source-type: git, bzr, hg, tar, zip, or subversion
@kyrofa

kyrofa Jun 13, 2016

Member

I know it's stupid, but can we have svn next to the other version control systems and leave tar and zip at the end?

snapcraft/internal/sources.py
@@ -359,6 +378,7 @@ def get_required_packages(options):
'mercurial': Mercurial,
'tar': Tar,
'zip': Zip,
+ 'subversion': Subversion,
@kyrofa

kyrofa Jun 13, 2016

Member

Is there a reason not to also resolve 'svn' to Subversion?

@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

Good point, nice catch, @elopio

snapcraft/tests/test_sources.py
+ svn = sources.Subversion('svn://my-source', 'source_dir')
+ svn.pull()
+ self.mock_run.assert_called_once_with(
+ ['svn', 'update', 'source-dir'])
@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

@elopio @chadmiller @kyrofa This line is causing something to fail, I think the unit tests? https://travis-ci.org/ubuntu-core/snapcraft/jobs/137352934

What do I need to correct to make this go away? Do I need to remove 'svn://my-source' from line 334?

@sergiusens

sergiusens Jun 13, 2016

Collaborator

on 334 you specify source_dir and on 337 you expect source-dir

@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

@sergiusens oh! nice catch, thanks.

snapcraft/internal/sources.py
+
+ def pull(self):
+ if os.path.exists(os.path.join(self.source_dir, '.svn')):
+ subprocess.check_call(
@sergiusens

sergiusens Jun 13, 2016

Collaborator

why not

subprocess.check_call(['svn', 'update'], cwd=self.source_dir)

?

@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

Good call, I'll make this change

snapcraft/internal/sources.py
@@ -348,6 +369,8 @@ def get_required_packages(options):
packages.append('tar')
elif source_type == 'hg' or source_type == 'mercurial':
packages.append('mercurial')
+ elif source_type == 'subversion':
@sergiusens

sergiusens Jun 13, 2016

Collaborator

this should be

elif source_type == 'subversion' or source_type == 'svn'
@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

Nice catch, I'm glad this was caught, I'll make the change

snapcraft/tests/test_sources.py
+ svn = sources.Subversion('svn://my-source', 'source_dir')
+ svn.pull()
+ self.mock_run.assert_called_once_with(
+ ['svn', 'update', 'source_dir'])
@sergiusens

sergiusens Jun 13, 2016

Collaborator

why not

self.mock_run.assert_called_once_with(['svn', 'update'], cwd=svn.source_dir)

if you take the advice from above

@tsimonq2

tsimonq2 Jun 13, 2016

Contributor

Yeah, I prefer this over the code I had. Thanks!

Collaborator

sergiusens commented Jun 13, 2016

For a proper integration test you will need to create this layout either on the fly or commited (on the fly might be more versatile)

Here's a shell snippet

svncreate repo
svn checkout file:///$(pwd)/repo checkout1 #  the source entry in the test code would use this
svn checkout file:///$(pwd)/repo checkout2
cd checkout2
touch some_file
svn add file
svn commit -m 'some file'
cd ../checkout1
svn update # this would be running pull again for the source
ls some_file
Collaborator

sergiusens commented Jun 13, 2016

@elopio do you mind looking at that integration test I mention ^^

tsimonq2 added some commits Jun 13, 2016

snapcraft/sources.py
@@ -20,4 +20,5 @@
from snapcraft.internal.sources import Tar # noqa
from snapcraft.internal.sources import Local # noqa
from snapcraft.internal.sources import Zip # noqa
+from snapcraft.internal.sources import Subversion
@sergiusens

sergiusens Jun 14, 2016

Collaborator

this is missing a # noqa statement, line it up with the Zip one above

@tsimonq2

tsimonq2 Jun 14, 2016

Contributor

All fixed, thanks :)

tsimonq2 added some commits Jun 14, 2016

integration_tests/test_svn_source.py
@@ -0,0 +1,75 @@
+# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
+#
+# Copyright (C) 2015 Canonical Ltd
integration_tests/test_svn_source.py
+ subprocess.check_call(
+ ['cd', '../testupdate'],stdout=subprocess.DEVNULL)
+ subprocess.check_call(
+ ['svn', 'update', '.'],stdout=subprocess.DEVNULL)
@elopio

elopio Jun 14, 2016

Member

As I discussed on irc, this is missing the calls to self.run_snapcraft('pull', project_dir)
The purpose of the tests is to test the pull, not svn.

snapcraft/internal/sources.py
+ super().__init__(source, source_dir, source_tag, source_branch)
+ if source_tag:
+ raise IncompatibleOptionsError(
+ 'can\'t specify a source-tag for a subversion source')
@elopio

elopio Jun 14, 2016

Member

When the string has a single quote, we usually write it with double quotes:
"can't specify a source-tag..."

snapcraft/internal/sources.py
+ 'can\'t specify a source-tag for a subversion source')
+ elif source_branch:
+ raise IncompatibleOptionsError(
+ 'can\'t specify a source-branch for a subversion source')
snapcraft/tests/test_sources.py
+ self.mock_run.assert_called_once_with(
+ ['svn', 'update'], cwd=svn.source_dir)
+
+
@elopio

elopio Jun 14, 2016

Member

you are missing two tests to check the errors when tag and branch are used.

tsimonq2 added some commits Jun 14, 2016

@@ -17,6 +17,7 @@
from snapcraft.internal.sources import Bazaar # noqa
from snapcraft.internal.sources import Git # noqa
from snapcraft.internal.sources import Mercurial # noqa
+from snapcraft.internal.sources import Subversion # noqa
from snapcraft.internal.sources import Tar # noqa
from snapcraft.internal.sources import Local # noqa
from snapcraft.internal.sources import Zip # noqa
@elopio

elopio Jun 14, 2016

Member

Can you please update the copyright year in this file to 2015, 2016 ?

@tsimonq2

tsimonq2 Jun 14, 2016

Contributor

Done

snapcraft/internal/sources.py
+ super().__init__(source, source_dir, source_tag, source_branch)
+ if source_tag:
+ raise IncompatibleOptionsError(
+ "can\'t specify a source-tag for a subversion source")
@elopio

elopio Jun 14, 2016

Member

you can remove the \

@tsimonq2

tsimonq2 Jun 14, 2016

Contributor

@elopio Bazaar has the same problem, I'll correct Subversion, but might it be worth a whole other PR to fix this?

tsimonq2 added some commits Jun 14, 2016

integration_tests/test_svn_source.py
+ stdout=subprocess.DEVNULL)
+
+ os.chdir("local/")
+ subprocess.check_call(['touch', 'file'],stdout=subprocess.DEVNULL)
@elopio

elopio Jun 14, 2016

Member

Generally we call subprocess when there is no good way to do it with pure python. In the case of touch, you can do instead:

open(os.path.join('local', 'file'), 'w').close()

integration_tests/test_svn_source.py
+
+ self.run_snapcraft('pull', project_dir)
+ revno = subprocess.check_output('svnversion parts/svn/src').strip()
+ self.assertEqual('"1"', revno)
@elopio

elopio Jun 14, 2016

Member

You can also check that the file exists.

@tsimonq2

tsimonq2 Jun 14, 2016

Contributor

@elopio Good call

@tsimonq2

tsimonq2 Jun 14, 2016

Contributor

Done

tsimonq2 added some commits Jun 14, 2016

Contributor

tsimonq2 commented Jun 14, 2016

@sergiusens Integrated ;)

Contributor

tsimonq2 commented Jun 14, 2016

This seems to me like it's close to done if not completely done given the feedback I've received. Does anybody notice anything else that I should correct?

tsimonq2 added some commits Jun 14, 2016

integration_tests/test_svn_source.py
+ ['svnadmin', 'create', 'repo'], stdout=subprocess.DEVNULL)
+
+ def test_pull_svn(self):
+
@elopio

elopio Jun 14, 2016

Member

a nit, remove this empty line.

integration_tests/test_svn_source.py
+ os.chdir("..")
+
+ self.run_snapcraft('pull', project_dir)
+ revno = subprocess.check_output('svnversion parts/svn/src').strip()
@elopio

elopio Jun 14, 2016

Member

please use os.path.join('parts', 'svn', 'src')
part_src_path = os.path.join('parts', 'svn', 'src')
revno = subprocess.check_output(['svnversion', parts_src_path]).strip()

integration_tests/test_svn_source.py
+ revno = subprocess.check_output('svnversion parts/svn/src').strip()
+ self.assertEqual('"1"', revno)
+ filepresent = os.path.isfile("parts/svn/src/file")
+ self.assertEqual('"True"', filepresent)
@elopio

elopio Jun 14, 2016

Member

You can use self.assertThat(os.path.join(parts_src_path, 'file'), FileExists())
Add to the top:
from testtools.matchers import FileExists. Between shutil and integration_tests, with empty lines around.

Member

elopio commented Jun 14, 2016

Looks good to me. Please rebase or merge with master, or hit the update button that git shows you here vvv.

integration_tests/test_svn_source.py
+ subprocess.check_call(['svn', 'update'],stdout=subprocess.DEVNULL)
+ subprocess.check_call(
+ ['rm', '-rf', 'local/'],stdout=subprocess.DEVNULL)
+ os.chdir("..")
@chadmiller

chadmiller Jun 14, 2016

The 'chdir's bother me. Use instead the "cwd" keyword on subprocess functions. Or at least try/finally to save and restore the current working dir for the process.

@tsimonq2

tsimonq2 Jun 14, 2016

Contributor

@chadmiller can you clarify what you mean by this?

@chadmiller

chadmiller Jun 14, 2016

subprocess.check_call( ['svn', 'add', 'file'],stdout=subprocess.DEVNULL, pwd=project_dir)

not

chdir
s.check_call

If this is a standalone test program, this doesn't matter very much, but changing global state in a test that continues past your test is a bad idea.

tsimonq2 added some commits Jun 14, 2016

integration_tests/test_svn_source.py
+ self._init_svn()
+
+ subprocess.check_call(
+ ['svn', 'checkout', 'file:///$(pwd)/repo', 'local'],
@chadmiller

chadmiller Jun 14, 2016

That $() is not going to do what you think unless subversion is going to interpret it, which I doubt. Please verify.

@tsimonq2

tsimonq2 Jun 14, 2016

Contributor

@chadmiller running that command works locally, and playing around with it, I'm not seeing another way to do it. I think it's fine.

@elopio

elopio Jun 14, 2016

Member

'file://{}'.format(os.path.join(project_dir, 'repo'))

@tsimonq2

tsimonq2 Jun 14, 2016

Contributor

@elopio thanks, didn't know that was something I could do!

tsimonq2 added some commits Jun 14, 2016

Contributor

tsimonq2 commented Jun 14, 2016

@chadmiller Does it look good now?

@elopio I've merged with master, it should be good to go now.

Member

elopio commented Jun 15, 2016

One more thing I forgot: please add subversion to debian/tests/control, on the integration section.

integration_tests/test_svn_source.py
+
+ open(os.path.join('local', 'file'), 'w').close()
+ subprocess.check_call(
+ ['svn', 'add', 'file'],stdout=subprocess.DEVNULL,cwd='local/')
@elopio

elopio Jun 15, 2016

Member

This will fail the pep8 check. You need to put one empty space after the commas.

Member

elopio commented Jun 15, 2016

Looking at the coveralls coverage, you are still missing one test for the uri.
Take a look in test_sources.py, the TestUri test case. You need to add one that's just like the git test.

tsimonq2 added some commits Jun 15, 2016

* Added the subversion build dependency to debian/tests/control
 * Added a TestUri test case in snapcraft/tests/test_sources.py for hopefully full coverage
 * Added empty spaces that are needed in integration_tests/test_svn_source.py
Contributor

tsimonq2 commented Jun 15, 2016

@elopio The only other thing I can think to fix is https://coveralls.io/builds/6601979/source?filename=snapcraft%2Finternal%2Fsources.py#L378

What file would I edit to add coverage for this?

Member

elopio commented Jun 16, 2016

Look at snapcraft/tests/test_yaml.py, test_config_adds_vcs_packages...

Contributor

tsimonq2 commented Jun 16, 2016

@elopio thanks

tsimonq2 added some commits Jun 16, 2016

Member

elopio commented Jun 16, 2016

OK to test

Member

elopio commented Jun 16, 2016

retest this please

tsimonq2 added some commits Jun 17, 2016

snapcraft/internal/sources.py
+ if self.source.startswith('svn:') or \
+ self.source.startswith('https:') or \
+ self.source.startswith('http:') or \
+ self.source.startswith('svn+ssh:'):
@elopio

elopio Jun 17, 2016

Member

I'm wondering what would be a better way to do this.
what about reversing the loging and
if os.path.isdir(self.source), append file://, else, leave it alone ?

@tsimonq2

tsimonq2 Jun 17, 2016

Contributor

@elopio I'll play around with this.

@tsimonq2

tsimonq2 Jun 17, 2016

Contributor

@elopio that's a better solution, thanks, pushing now

tsimonq2 added some commits Jun 17, 2016

* Changed the logic of the svn checkout thanks to Leo Arias
 * Reindented some code, hopefully fixing the Travis static build
* Added unit test for local svn repository checkout
 * Fixed build error due to the lack of an empty line in snapcraft/internal/sources.py
snapcraft/tests/test_sources.py
+ self.mock_run.assert_called_once_with(
+ ['svn', 'checkout',
+ 'file://{}'.format(os.path.abspath('my-source/')),
+ 'source_dir'])
@elopio

elopio Jun 17, 2016

Member

notice that here you are not testing anything, because you are passing to the Subversion constructor a source that will return false in isdir.
On the constructor, pass only 'my-source'.

tsimonq2 added some commits Jun 17, 2016

+ subprocess.check_call(
+ ['svnadmin', 'create', 'repo'], stdout=subprocess.DEVNULL)
+
+ def test_pull_svn(self):
@elopio

elopio Jun 17, 2016

Member

You can put this test in the same file as the other. Call one test_pull_svn_checkout and the other test_pull_svn_update.

@tsimonq2

tsimonq2 Jun 17, 2016

Contributor

Oh okay, I'll do this, thanks

tsimonq2 added some commits Jun 17, 2016

@tsimonq2 tsimonq2 changed the title from Added Subversion support to Add Subversion support Jun 18, 2016

Contributor

tsimonq2 commented Jun 20, 2016

Seems like the autopkgtest failure is not related to my snap if I'm reading this correctly: http://paste.ubuntu.com/17582500/

Contributor

tsimonq2 commented Jun 20, 2016

Nope, found it

integration_tests/test_svn_pull.py
+ part_src_path = os.path.join('parts', 'svn', 'src')
+ self.run_snapcraft('pull', project_dir)
+ revno = subprocess.check_output(['svnversion', part_src_path]).strip()
+ self.assertEqual(1, revno)
@tsimonq2

tsimonq2 Jun 21, 2016

Contributor

This is causing the integration test errors. I have no clue what I can do to fix this. Thoughts? @elopio

@elopio

elopio Jun 22, 2016

Member

Hey, sorry for the delay.
check_output never returns an int. By default, it returns bytes. I think it's better if you pass universal_newlines=True, and then assertEqual('1', revno)

@tsimonq2

tsimonq2 Jun 22, 2016

Contributor

thanks @elopio

@tsimonq2 tsimonq2 referenced this pull request in Ubuntu/snappy-playpen Jun 21, 2016

Open

Added a Sylpheed snap #60

0 of 1 task complete

tsimonq2 added some commits Jun 22, 2016

@sergiusens sergiusens merged commit 0e1ec16 into snapcore:master Jun 22, 2016

4 checks passed

Examples tests Success
Details
autopkgtest Success
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
coverage/coveralls Coverage decreased (-0.02%) to 95.915%
Details

@tsimonq2 tsimonq2 deleted the tsimonq2:svn branch Jul 7, 2016

kalikiana pushed a commit to kalikiana/snapcraft that referenced this pull request Apr 6, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment