1
0
mirror of https://github.com/openSUSE/osc.git synced 2024-11-15 08:36:13 +01:00
github.com_openSUSE_osc/tests/test_commit.py
Daniel Mach a887ade78f Fix possibility to overwrite special files in .osc (CVE-2024-22034 boo#1225911)
Source files are now stored in the 'sources' subdirectory which prevents
name collisons. This requires changing version of '.osc' store to 2.0.
2024-07-29 13:24:13 +02:00

377 lines
22 KiB
Python

import os
import sys
import unittest
from urllib.error import HTTPError
from xml.etree import ElementTree as ET
import osc.core
import osc.oscerr
from .common import GET, PUT, POST, DELETE, OscTestCase
FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'commit_fixtures')
def suite():
return unittest.defaultTestLoader.loadTestsFromTestCase(TestCommit)
rev_dummy = '<revision rev="repository">\n <srcmd5>empty</srcmd5>\n</revision>'
class TestCommit(OscTestCase):
def _get_fixtures_dir(self):
return FIXTURES_DIR
@GET('http://localhost/source/osctest/simple?rev=latest', file='testSimple_filesremote')
@POST('http://localhost/source/osctest/simple?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testSimple_missingfilelist', expfile='testSimple_lfilelist')
@PUT('http://localhost/source/osctest/simple/nochange?rev=repository',
exp='This file didn\'t change but\nis modified.\n', text=rev_dummy)
@POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin',
file='testSimple_cfilesremote', expfile='testSimple_lfilelist')
@GET('http://localhost/request?view=collection&project=osctest&package=simple&states=new%2Creview', file='testOpenRequests')
def test_simple(self):
"""a simple commit (only one modified file)"""
self._change_to_pkg('simple')
p = osc.core.Package('.')
p.commit()
exp = 'Sending nochange\nTransmitting file data .\nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testSimple_cfilesremote')
self.assertTrue(os.path.exists('nochange'))
self.assertFilesEqual('nochange', os.path.join('.osc', 'sources', 'nochange'))
self._check_status(p, 'nochange', ' ')
self._check_status(p, 'foo', ' ')
self._check_status(p, 'merge', ' ')
@GET('http://localhost/source/osctest/add?rev=latest', file='testAddfile_filesremote')
@POST('http://localhost/source/osctest/add?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/add?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testAddfile_missingfilelist', expfile='testAddfile_lfilelist')
@PUT('http://localhost/source/osctest/add/add?rev=repository',
exp='added file\n', text=rev_dummy)
@POST('http://localhost/source/osctest/add?comment=&cmd=commitfilelist&user=Admin',
file='testAddfile_cfilesremote', expfile='testAddfile_lfilelist')
@GET('http://localhost/request?view=collection&project=osctest&package=add&states=new%2Creview', file='testOpenRequests')
def test_addfile(self):
"""commit a new file"""
self._change_to_pkg('add')
p = osc.core.Package('.')
p.commit()
exp = 'Sending add\nTransmitting file data .\nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testAddfile_cfilesremote')
self.assertTrue(os.path.exists('add'))
self.assertFilesEqual('add', os.path.join('.osc', 'sources', 'add'))
self.assertFalse(os.path.exists(os.path.join('.osc', '_to_be_added')))
self._check_status(p, 'add', ' ')
self._check_status(p, 'foo', ' ')
self._check_status(p, 'merge', ' ')
self._check_status(p, 'nochange', ' ')
@GET('http://localhost/source/osctest/delete?rev=latest', file='testDeletefile_filesremote')
@POST('http://localhost/source/osctest/delete?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/delete?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testDeletefile_cfilesremote', expfile='testDeletefile_lfilelist')
@GET('http://localhost/request?view=collection&project=osctest&package=delete&states=new%2Creview', file='testOpenRequests')
def test_deletefile(self):
"""delete a file"""
self._change_to_pkg('delete')
p = osc.core.Package('.')
p.commit()
exp = 'Deleting nochange\nTransmitting file data \nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testDeletefile_cfilesremote')
self.assertFalse(os.path.exists('nochange'))
self.assertFalse(os.path.exists(os.path.join('.osc', 'sources', 'nochange')))
self.assertFalse(os.path.exists(os.path.join('.osc', '_to_be_deleted')))
self._check_status(p, 'foo', ' ')
self._check_status(p, 'merge', ' ')
@GET('http://localhost/source/osctest/conflict?rev=latest', file='testConflictfile_filesremote')
@POST('http://localhost/source/osctest/conflict?cmd=getprojectservices',
exp='', text='<services />')
def test_conflictfile(self):
"""package has a file which is in conflict state"""
self._change_to_pkg('conflict')
ret = osc.core.Package('.').commit()
self.assertTrue(ret == 1)
exp = 'Please resolve all conflicts before committing using "osc resolved FILE"!\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testConflictfile_filesremote')
self._check_conflictlist('merge\n')
@GET('http://localhost/source/osctest/nochanges?rev=latest', file='testNoChanges_filesremote')
@POST('http://localhost/source/osctest/nochanges?cmd=getprojectservices',
exp='', text='<services />')
def test_nochanges(self):
"""package has no changes (which can be committed)"""
self._change_to_pkg('nochanges')
p = osc.core.Package('.')
ret = p.commit()
self.assertTrue(ret == 1)
exp = 'nothing to do for package nochanges\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_status(p, 'foo', 'S')
self._check_status(p, 'merge', '!')
self._check_status(p, 'nochange', ' ')
@GET('http://localhost/source/osctest/multiple?rev=latest', file='testMultiple_filesremote')
@POST('http://localhost/source/osctest/multiple?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/multiple?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testMultiple_missingfilelist', expfile='testMultiple_lfilelist')
@PUT('http://localhost/source/osctest/multiple/nochange?rev=repository', exp='This file did change.\n', text=rev_dummy)
@PUT('http://localhost/source/osctest/multiple/add?rev=repository', exp='added file\n', text=rev_dummy)
@PUT('http://localhost/source/osctest/multiple/add2?rev=repository', exp='add2\n', text=rev_dummy)
@POST('http://localhost/source/osctest/multiple?comment=&cmd=commitfilelist&user=Admin',
file='testMultiple_cfilesremote', expfile='testMultiple_lfilelist')
@GET('http://localhost/request?view=collection&project=osctest&package=multiple&states=new%2Creview', file='testOpenRequests')
def test_multiple(self):
"""a simple commit (only one modified file)"""
self._change_to_pkg('multiple')
p = osc.core.Package('.')
p.commit()
exp = 'Deleting foo\nDeleting merge\nSending nochange\n' \
'Sending add\nSending add2\nTransmitting file data ...\nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testMultiple_cfilesremote')
self.assertFalse(os.path.exists(os.path.join('.osc', '_to_be_added')))
self.assertFalse(os.path.exists(os.path.join('.osc', '_to_be_deleted')))
self.assertFalse(os.path.exists(os.path.join('.osc', 'sources', 'foo')))
self.assertFalse(os.path.exists(os.path.join('.osc', 'sources', 'merge')))
self.assertRaises(osc.oscerr.OscIOError, p.status, 'foo')
self.assertRaises(osc.oscerr.OscIOError, p.status, 'merge')
self._check_status(p, 'add', ' ')
self._check_status(p, 'add2', ' ')
self._check_status(p, 'nochange', ' ')
@GET('http://localhost/source/osctest/multiple?rev=latest', file='testPartial_filesremote')
@POST('http://localhost/source/osctest/multiple?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/multiple?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testPartial_missingfilelist', expfile='testPartial_lfilelist')
@PUT('http://localhost/source/osctest/multiple/add?rev=repository', exp='added file\n', text=rev_dummy)
@PUT('http://localhost/source/osctest/multiple/nochange?rev=repository', exp='This file did change.\n', text=rev_dummy)
@POST('http://localhost/source/osctest/multiple?comment=&cmd=commitfilelist&user=Admin',
file='testPartial_cfilesremote', expfile='testPartial_lfilelist')
@GET('http://localhost/request?view=collection&project=osctest&package=multiple&states=new%2Creview', file='testOpenRequests')
def test_partial(self):
"""commit only some files"""
self._change_to_pkg('multiple')
p = osc.core.Package('.')
p.todo = ['foo', 'add', 'nochange']
p.commit()
exp = 'Deleting foo\nSending nochange\n' \
'Sending add\nTransmitting file data ..\nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testPartial_cfilesremote')
self._check_addlist('add2\n')
self._check_deletelist('merge\n')
self._check_status(p, 'add2', 'A')
self._check_status(p, 'merge', 'D')
self._check_status(p, 'add', ' ')
self._check_status(p, 'nochange', ' ')
self.assertRaises(osc.oscerr.OscIOError, p.status, 'foo')
@GET('http://localhost/source/osctest/simple?rev=latest', file='testSimple_filesremote')
@POST('http://localhost/source/osctest/simple?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testSimple_missingfilelist', expfile='testSimple_lfilelist')
@PUT('http://localhost/source/osctest/simple/nochange?rev=repository', exp='This file didn\'t change but\nis modified.\n',
exception=IOError('test exception'), text=rev_dummy)
def test_interrupt(self):
"""interrupt a commit"""
self._change_to_pkg('simple')
p = osc.core.Package('.')
self.assertRaises(IOError, p.commit)
exp = 'Sending nochange\nTransmitting file data .'
self.assertTrue(sys.stdout.getvalue(), exp)
self._check_digests('testSimple_filesremote')
self.assertTrue(os.path.exists('nochange'))
self._check_status(p, 'nochange', 'M')
@GET('http://localhost/source/osctest/allstates?rev=latest', file='testPartial_filesremote')
@POST('http://localhost/source/osctest/allstates?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/allstates?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testAllStates_missingfilelist', expfile='testAllStates_lfilelist')
@PUT('http://localhost/source/osctest/allstates/add?rev=repository', exp='added file\n', text=rev_dummy)
@PUT('http://localhost/source/osctest/allstates/missing?rev=repository', exp='replaced\n', text=rev_dummy)
@PUT('http://localhost/source/osctest/allstates/nochange?rev=repository', exp='This file did change.\n', text=rev_dummy)
@POST('http://localhost/source/osctest/allstates?comment=&cmd=commitfilelist&user=Admin',
file='testAllStates_cfilesremote', expfile='testAllStates_lfilelist')
@GET('http://localhost/request?view=collection&project=osctest&package=allstates&states=new%2Creview', file='testOpenRequests')
def test_allstates(self):
"""commit all files (all states are available except 'C')"""
self._change_to_pkg('allstates')
p = osc.core.Package('.')
p.commit()
exp = 'Deleting foo\nSending missing\nSending nochange\n' \
'Sending add\nTransmitting file data ...\nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testAllStates_expfiles', 'skipped')
self.assertFalse(os.path.exists(os.path.join('.osc', '_to_be_added')))
self.assertFalse(os.path.exists(os.path.join('.osc', '_to_be_deleted')))
self.assertFalse(os.path.exists('foo'))
self.assertFalse(os.path.exists(os.path.join('.osc', 'sources', 'foo')))
self._check_status(p, 'add', ' ')
self._check_status(p, 'nochange', ' ')
self._check_status(p, 'merge', '!')
self._check_status(p, 'missing', ' ')
self._check_status(p, 'skipped', 'S')
self._check_status(p, 'test', ' ')
@GET('http://localhost/source/osctest/add?rev=latest', file='testAddfile_filesremote')
@POST('http://localhost/source/osctest/add?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/add?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testAddfile_cfilesremote', expfile='testAddfile_lfilelist')
@GET('http://localhost/request?view=collection&project=osctest&package=add&states=new%2Creview', file='testOpenRequests')
def test_remoteexists(self):
"""file 'add' should be committed but already exists on the server"""
self._change_to_pkg('add')
p = osc.core.Package('.')
p.commit()
exp = 'Sending add\nTransmitting file data \nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testAddfile_cfilesremote')
self.assertTrue(os.path.exists('add'))
self.assertFilesEqual('add', os.path.join('.osc', 'sources', 'add'))
self.assertFalse(os.path.exists(os.path.join('.osc', '_to_be_added')))
self._check_status(p, 'add', ' ')
self._check_status(p, 'foo', ' ')
self._check_status(p, 'merge', ' ')
self._check_status(p, 'nochange', ' ')
@GET('http://localhost/source/osctest/branch?rev=latest', file='testExpand_filesremote')
@POST('http://localhost/source/osctest/branch?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/branch?comment=&cmd=commitfilelist&user=Admin&withvalidate=1&keeplink=1',
file='testExpand_missingfilelist', expfile='testExpand_lfilelist')
@PUT('http://localhost/source/osctest/branch/simple?rev=repository', exp='simple modified file.\n', text=rev_dummy)
@POST('http://localhost/source/osctest/branch?comment=&cmd=commitfilelist&user=Admin&keeplink=1',
file='testExpand_cfilesremote', expfile='testExpand_lfilelist')
@GET('http://localhost/source/osctest/branch?rev=87ea02aede261b0267aabaa97c756e7a', file='testExpand_expandedfilesremote')
@GET('http://localhost/request?view=collection&project=osctest&package=branch&states=new%2Creview', file='testOpenRequests')
def test_expand(self):
"""commit an expanded package"""
self._change_to_pkg('branch')
p = osc.core.Package('.')
p.commit()
exp = 'Sending simple\nTransmitting file data .\nCommitted revision 7.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testExpand_expandedfilesremote')
self._check_status(p, 'simple', ' ')
@GET('http://localhost/source/osctest/added_missing?rev=latest', file='testAddedMissing_filesremote')
@POST('http://localhost/source/osctest/added_missing?cmd=getprojectservices',
exp='', text='<services />')
def test_added_missing(self):
"""commit an added file which is missing"""
self._change_to_pkg('added_missing')
p = osc.core.Package('.')
ret = p.commit()
self.assertTrue(ret == 1)
exp = 'file \'add\' is marked as \'A\' but does not exist\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_status(p, 'add', '!')
@GET('http://localhost/source/osctest/added_missing?rev=latest', file='testAddedMissing_filesremote')
@POST('http://localhost/source/osctest/added_missing?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/added_missing?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testAddedMissing_missingfilelist', expfile='testAddedMissing_lfilelist')
@PUT('http://localhost/source/osctest/added_missing/bar?rev=repository', exp='foobar\n', text=rev_dummy)
@POST('http://localhost/source/osctest/added_missing?comment=&cmd=commitfilelist&user=Admin',
file='testAddedMissing_cfilesremote', expfile='testAddedMissing_lfilelist')
@GET('http://localhost/request?view=collection&project=osctest&package=added_missing&states=new%2Creview', file='testOpenRequests')
def test_added_missing2(self):
"""commit an added file, another added file missing (but it's not part of the commit)"""
self._change_to_pkg('added_missing')
p = osc.core.Package('.')
p.todo = ['bar']
p.commit()
exp = 'Sending bar\nTransmitting file data .\nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_status(p, 'add', '!')
self._check_status(p, 'bar', ' ')
@GET('http://localhost/source/osctest/simple?rev=latest', file='testSimple_filesremote')
@POST('http://localhost/source/osctest/simple?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testSimple_missingfilelist', expfile='testSimple_lfilelist')
@PUT('http://localhost/source/osctest/simple/nochange?rev=repository',
exp='This file didn\'t change but\nis modified.\n', text=rev_dummy)
@POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin',
expfile='testSimple_lfilelist', text='an error occured', code=500)
def test_commitfilelist_error(self):
"""commit modified file but when committing the filelist the server returns status 500 (see ticket #65)"""
self._change_to_pkg('simple')
p = osc.core.Package('.')
self._check_status(p, 'nochange', 'M')
self.assertRaises(HTTPError, p.commit)
exp = 'Sending nochange\nTransmitting file data .'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_status(p, 'nochange', 'M')
@GET('http://localhost/source/osctest/simple?rev=latest', file='testSimple_filesremote')
@POST('http://localhost/source/osctest/simple?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testSimple_missingfilelistwithSHA', expfile='testSimple_lfilelist')
@POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin',
file='testSimple_missingfilelistwithSHAsum', expfile='testSimple_lfilelistwithSHA')
@PUT('http://localhost/source/osctest/simple/nochange?rev=repository',
exp='This file didn\'t change but\nis modified.\n', text=rev_dummy)
@POST('http://localhost/source/osctest/simple?comment=&cmd=commitfilelist&user=Admin',
file='testSimple_cfilesremote', expfile='testSimple_lfilelistwithSHA')
@GET('http://localhost/request?view=collection&project=osctest&package=simple&states=new%2Creview', file='testOpenRequests')
def test_simple_sha256(self):
"""a simple commit (only one modified file)"""
self._change_to_pkg('simple')
p = osc.core.Package('.')
p.commit()
exp = 'Sending nochange\nTransmitting file data .\nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_digests('testSimple_cfilesremote')
self.assertTrue(os.path.exists('nochange'))
self.assertFilesEqual('nochange', os.path.join('.osc', 'sources', 'nochange'))
self._check_status(p, 'nochange', ' ')
self._check_status(p, 'foo', ' ')
self._check_status(p, 'merge', ' ')
@GET('http://localhost/source/osctest/added_missing?rev=latest', file='testAddedMissing_filesremote')
@POST('http://localhost/source/osctest/added_missing?cmd=getprojectservices',
exp='', text='<services />')
@POST('http://localhost/source/osctest/added_missing?comment=&cmd=commitfilelist&user=Admin&withvalidate=1',
file='testAddedMissing_missingfilelistwithSHA', expfile='testAddedMissing_lfilelist')
@POST('http://localhost/source/osctest/added_missing?comment=&cmd=commitfilelist&user=Admin',
file='testAddedMissing_missingfilelistwithSHAsum', expfile='testAddedMissing_lfilelistwithSHA')
@PUT('http://localhost/source/osctest/added_missing/bar?rev=repository', exp='foobar\n', text=rev_dummy)
@POST('http://localhost/source/osctest/added_missing?comment=&cmd=commitfilelist&user=Admin',
file='testAddedMissing_cfilesremote', expfile='testAddedMissing_lfilelistwithSHA')
@GET('http://localhost/request?view=collection&project=osctest&package=added_missing&states=new%2Creview', file='testOpenRequests')
def test_added_missing2_sha256(self):
"""commit an added file, another added file missing (but it's not part of the commit)"""
self._change_to_pkg('added_missing')
p = osc.core.Package('.')
p.todo = ['bar']
p.commit()
exp = 'Sending bar\nTransmitting file data .\nCommitted revision 2.\n'
self.assertEqual(sys.stdout.getvalue(), exp)
self._check_status(p, 'add', '!')
self._check_status(p, 'bar', ' ')
if __name__ == '__main__':
unittest.main()