Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#96 #169: Add options and tests for several methods #190

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/dist/
/.DS_Store
/build/
/cover/
*.pyc
venv*
*.svn
Expand All @@ -15,4 +16,5 @@ venv*
.tox
/pip-selfcheck.json
/man
.mypy_cache
.python-version
61 changes: 43 additions & 18 deletions svn/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
_HUNK_HEADER_LINE_NUMBERS_PREFIX = '@@ '


def get_depth_options(depth, is_set_depth=False):
"""Get options for depth and check (is_set_depth=True for --set-depth)"""
depth_values = {"empty", "files", "immediates", "infinity"}
if is_set_depth:
depth_values = depth_values.union({"exclude"})

if depth not in depth_values:
raise svn.exception.SvnException(
"Invalid depth '{d}' (values allowed: {v})!".format(d=depth, v=depth_values)
)

return ["--set-depth" if is_set_depth else "--depth", depth]


class CommonClient(svn.common_base.CommonBase):
def __init__(self, url_or_path, type_, username=None, password=None,
svn_filepath='svn', trust_cert=None, env={}, *args, **kwargs):
Expand Down Expand Up @@ -61,7 +75,7 @@ def __element_text(self, element):

return None

def info(self, rel_path=None, revision=None):
def info(self, rel_path=None, revision=None, include_ext=False):
cmd = []
if revision is not None:
cmd += ['-r', str(revision)]
Expand All @@ -70,6 +84,8 @@ def info(self, rel_path=None, revision=None):
if rel_path is not None:
full_url_or_path += '/' + rel_path
cmd += ['--xml', full_url_or_path]
if include_ext:
cmd += ["--include-externals"]

result = self.run_command(
'info',
Expand All @@ -79,7 +95,8 @@ def info(self, rel_path=None, revision=None):
root = xml.etree.ElementTree.fromstring(result)

entry_attr = root.find('entry').attrib
commit_attr = root.find('entry/commit').attrib
commit_tag = root.find('entry/commit')
commit_attr = commit_tag.attrib if commit_tag else None

relative_url = root.find('entry/relative-url')
author = root.find('entry/commit/author')
Expand All @@ -97,20 +114,22 @@ def info(self, rel_path=None, revision=None):

'entry#kind': entry_attr['kind'],
'entry#path': entry_attr['path'],
'entry#revision': int(entry_attr['revision']),

'repository/root': root.find('entry/repository/root').text,
'repository/uuid': root.find('entry/repository/uuid').text,

'wc-info/wcroot-abspath': self.__element_text(wcroot_abspath),
'wc-info/schedule': self.__element_text(wcinfo_schedule),
'wc-info/depth': self.__element_text(wcinfo_depth),
'commit/author': self.__element_text(author),

'commit/date': dateutil.parser.parse(
root.find('entry/commit/date').text),
'commit#revision': int(commit_attr['revision']),
'wc-info/depth': self.__element_text(wcinfo_depth)
}
if commit_attr:
info.update({
'entry#revision': int(entry_attr['revision']),
'commit/author': self.__element_text(author),
'commit/date': dateutil.parser.parse(
root.find('entry/commit/date').text),
'commit#revision': int(commit_attr['revision']),
})

# Set some more intuitive keys, because no one likes dealing with
# symbols. However, we retain the old ones to maintain backwards-
Expand All @@ -121,15 +140,17 @@ def info(self, rel_path=None, revision=None):

info['entry_kind'] = info['entry#kind']
info['entry_path'] = info['entry#path']
info['entry_revision'] = info['entry#revision']
info['repository_root'] = info['repository/root']
info['repository_uuid'] = info['repository/uuid']
info['wcinfo_wcroot_abspath'] = info['wc-info/wcroot-abspath']
info['wcinfo_schedule'] = info['wc-info/schedule']
info['wcinfo_depth'] = info['wc-info/depth']
info['commit_author'] = info['commit/author']
info['commit_date'] = info['commit/date']
info['commit_revision'] = info['commit#revision']

if commit_attr:
info['entry_revision'] = info['entry#revision']
info['commit_author'] = info['commit/author']
info['commit_date'] = info['commit/date']
info['commit_revision'] = info['commit#revision']

return info

Expand Down Expand Up @@ -285,23 +306,27 @@ def export(self, to_path, revision=None, force=False):

self.run_command('export', cmd)

def list(self, extended=False, rel_path=None):
def list(self, extended=False, rel_path=None, depth=None, include_ext=False):
full_url_or_path = self.__url_or_path
if rel_path is not None:
full_url_or_path += '/' + rel_path

cmd = [full_url_or_path]
if depth:
cmd += get_depth_options(depth)
if include_ext:
cmd += ["--include-externals"]

if extended is False:
for line in self.run_command(
'ls',
[full_url_or_path]):
for line in self.run_command('ls', cmd):
line = line.strip()
if line:
yield line

else:
raw = self.run_command(
'ls',
['--xml', full_url_or_path],
['--xml'] + cmd,
do_combine=True)

root = xml.etree.ElementTree.fromstring(raw)
Expand Down
37 changes: 31 additions & 6 deletions svn/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,54 @@ def __init__(self, path_, *args, **kwargs):
def __repr__(self):
return '<SVN(LOCAL) %s>' % self.path

def add(self, rel_path, do_include_parents=False):
def add(self, rel_path, do_include_parents=False, depth=None):
args = [rel_path]

if do_include_parents is True:
if do_include_parents:
args.append('--parents')
if depth:
args += svn.common.get_depth_options(depth)

self.run_command(
'add',
args,
wd=self.path)

def commit(self, message, rel_filepaths=[]):
args = ['-m', message] + rel_filepaths
def commit(self, message, rel_filepaths=None, depth=None, include_ext=False):
args = ['-m', message]
if depth:
args += svn.common.get_depth_options(depth)
if include_ext:
args += ["--include-externals"]
if rel_filepaths:
args += rel_filepaths

output = self.run_command(
'commit',
args,
wd=self.path)

def update(self, rel_filepaths=[], revision=None):
def update(
self,
rel_filepaths=[],
revision=None,
force=False,
depth=None,
set_depth=None,
ignore_ext=False,
):
cmd = []
if revision is not None:
cmd += ['-r', str(revision)]
cmd += ["-r", str(revision)]
if force:
cmd += ["--force"]
if depth:
cmd += svn.common.get_depth_options(depth)
if set_depth:
cmd += svn.common.get_depth_options(set_depth, is_set_depth=True)
if ignore_ext:
cmd += ["--ignore-externals"]

cmd += rel_filepaths
self.run_command(
'update',
Expand Down
8 changes: 7 additions & 1 deletion svn/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ def __init__(self, url, *args, **kwargs):
svn.constants.LT_URL,
*args, **kwargs)

def checkout(self, path, revision=None):
def checkout(self, path, revision=None, force=False, depth=None, ignore_ext=False):
cmd = []
if revision is not None:
cmd += ['-r', str(revision)]
if force:
cmd += ["--force"]
if depth:
cmd += svn.common.get_depth_options(depth)
if ignore_ext:
cmd += ["--ignore-externals"]

cmd += [self.url, path]

Expand Down
56 changes: 40 additions & 16 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@ def test_update(self):
lc.update()
self.assertEqual(3, lc.info()['commit_revision'])

lc.update(revision=1)
lc.update(set_depth="files")
self.assertEqual("files", lc.info()['wcinfo_depth'])

lc.update(depth="empty") # depth is not changed
self.assertEqual("files", lc.info()['wcinfo_depth'])

lc.update(revision=1, ignore_ext=True)
# TODO: ignore_ext not really tested
self.assertEqual(1, lc.info()['commit_revision'])

def test_diff_summary(self):
Expand Down Expand Up @@ -114,37 +121,40 @@ def test_list(self):
with svn.test_support.temp_common() as (_, _, cc):
svn.test_support.populate_bigger_file_changes1()

entries = cc.list()
entries = sorted(entries)

expected = [
'committed_changed',
'committed_deleted',
'committed_unchanged',
'new_file',
]

self.assertEqual(entries, expected)
entries = cc.list()
self.assertListEqual(sorted(entries), expected)

empty_entries = cc.list(depth="empty")
self.assertListEqual(list(empty_entries), [])

entries = cc.list(include_ext=True)
self.assertListEqual(sorted(entries), expected)
# TODO: include_ext/--include-externals not really tested

def test_info(self):
with svn.test_support.temp_common() as (repo_path, _, cc):
svn.test_support.populate_bigger_file_changes1()

info = cc.info()

self.assertEqual(
info['entry_path'],
'.')

self.assertEqual(info['entry_path'], '.')
uri = 'file://{}'.format(repo_path)
self.assertEqual(info['repository_root'], uri)
self.assertEqual(info['entry_kind'], 'dir')

self.assertEqual(
info['repository_root'],
uri)
info = cc.info(revision=1)
self.assertEqual(info['commit_revision'], 1)

self.assertEqual(
info['entry#kind'],
'dir')
info = cc.info(include_ext=True)
self.assertIsNotNone(info)
# TODO: include_ext/--include-externals not really tested

def test_info_revision(self):
with svn.test_support.temp_common() as (_, working_path, cc):
Expand All @@ -161,9 +171,23 @@ def test_info_revision(self):
info1 = cc.info(revision=1)
self.assertEquals(info1['commit_revision'], 1)

info2 = cc.info(revision=2)
info2 = cc.info(".", revision=2)
self.assertEquals(info2['commit_revision'], 2)

rel_filepath_not_committed = "to_be_added"
with open(rel_filepath_not_committed, 'w') as _:
pass
lc.add(rel_filepath_not_committed)

# Get information on file not yet committed to SVN
info3 = cc.info(rel_filepath_not_committed)
self.assertEquals(info3['wcinfo_schedule'], "add")
self.assertEqual(info3['entry_kind'], 'file')
self.assertNotIn('entry_revision', info3)
for attr in {"date", "revision", "author"}:
self.assertNotIn('commit_' + attr, info3)


def test_log(self):
with svn.test_support.temp_common() as (_, _, cc):
svn.test_support.populate_bigger_file_changes1()
Expand Down
Loading