Skip to content

Commit

Permalink
checkin: recreate ABAP Class if it already exists
Browse files Browse the repository at this point in the history
While checkin of ABAP class, if it already exists we delete it first and
then create.

I added check for the package name to avoid deleting class of different
package (from the one that is checked in to).

Fixes #116
  • Loading branch information
palubaj authored and jfilak committed Sep 8, 2023
1 parent 682ab6c commit b9ba9aa
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 9 deletions.
16 changes: 14 additions & 2 deletions sap/cli/checkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,20 @@ def checkin_clas(connection, repo_obj, corrnr=None):

try:
clas.create(corrnr)
except sap.adt.errors.ExceptionResourceAlreadyExists as err:
mod_log().info(err.message)
except sap.adt.errors.ExceptionResourceAlreadyExists as exc:
mod_log().info('Class already exists. Recreating.')
clas.fetch()

# pylint: disable=no-member
if clas.reference.name != repo_obj.package.name:
raise sap.adt.errors.ExceptionCheckinFailure(f'Cannot checkin class {repo_obj.name} into package'
f' {repo_obj.package.name}. It already exists in package'
f' {clas.reference.name}.') from exc

clas.delete(corrnr)
# Recreate class object to avoid stale data, which causes create to fail
clas = sap.adt.Class(connection, repo_obj.name.upper(), package=repo_obj.package.name, metadata=metadata)
clas.create(corrnr)

for source_file in repo_obj.files:
if not source_file.endswith('.abap'):
Expand Down
49 changes: 42 additions & 7 deletions test/unit/test_sap_cli_checkin.py
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,10 @@ def setUp(self):
self.clas_editor = MagicMock()
self.clas_editor.__enter__.return_value = self.clas_editor

self.clas = MagicMock()
self.package_reference = Mock()
self.package_reference.name = 'test_package'

self.clas = MagicMock(reference=self.package_reference)
self.clas.open_editor.return_value = self.clas_editor
self.clas.definitions.open_editor.return_value = self.clas_editor
self.clas.implementations.open_editor.return_value = self.clas_editor
Expand Down Expand Up @@ -618,6 +621,16 @@ def test_checkin_clas(self):
Writing Clas: {self.clas_object.name} testclasses
''')

def test_checkin_clas_already_exists(self):
self.fake_open.return_value = StringIOFile(CLAS_XML)
self.clas.create.side_effect = [ExceptionResourceAlreadyExists('Class already exists.'), None]

sap.cli.checkin.checkin_clas(self.connection, self.clas_object)

self.clas.fetch.assert_called_once()
self.clas.delete.assert_called_once()
self.clas.create.assert_has_calls([call(None), call(None)])

def test_checkin_clas_with_corrnr(self):
self.fake_open.return_value = StringIOFile(CLAS_XML)

Expand All @@ -626,15 +639,37 @@ def test_checkin_clas_with_corrnr(self):
self.clas.create.assert_called_once_with('corrnr')
self.assert_open_editor_calls([], corrnr='corrnr')

@patch('sap.cli.checkin.mod_log')
def test_checkin_clas_create_error(self, fake_mod_log):
def test_checkin_clas_already_exists_with_corrnr(self):
self.fake_open.return_value = StringIOFile(CLAS_XML)
self.clas.create.side_effect = ExceptionResourceAlreadyExists('Clas already created.')
self.clas.create.side_effect = [ExceptionResourceAlreadyExists('Class already exists.'), None]

sap.cli.checkin.checkin_clas(self.connection, self.clas_object)
sap.cli.checkin.checkin_clas(self.connection, self.clas_object, 'corrnr')

self.clas.fetch.assert_called_once()
self.clas.delete.assert_called_once_with('corrnr')
self.clas.create.assert_has_calls([call('corrnr'), call('corrnr')])

def test_checkin_clas_in_different_package(self):
self.fake_open.return_value = StringIOFile(CLAS_XML)
self.clas.create.side_effect = ExceptionResourceAlreadyExists('Class already exists.')
self.package_reference.name = 'different_package'

with self.assertRaises(ExceptionCheckinFailure) as cm:
sap.cli.checkin.checkin_clas(self.connection, self.clas_object)

self.assertEqual(str(cm.exception),
f'Cannot checkin class {self.clas_object.name} into package {self.package.name}.'
' It already exists in package different_package.')

def test_checkin_clas_create_error(self):
self.fake_open.return_value = StringIOFile(CLAS_XML)
self.clas.create.side_effect = SAPCliError('Class creation failed.')

with self.assertRaises(SAPCliError) as cm:
sap.cli.checkin.checkin_clas(self.connection, self.clas_object)

fake_mod_log.return_value.info.assert_called_once_with('Clas already created.')
self.assert_open_editor_calls([])
self.assertEqual(str(cm.exception), 'Class creation failed.')
self.clas.object_editor.assert_not_called()

def test_checkin_clas_source_file_wrong_suffix(self):
self.fake_open.return_value = StringIOFile(CLAS_XML)
Expand Down

0 comments on commit b9ba9aa

Please sign in to comment.