From b6b333c62592d364932148f6d72adf28b526b8b5 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Thu, 1 Dec 2016 09:54:17 -0500 Subject: [PATCH 01/24] Add schema and metadata entries for the TUF specification version number --- tuf/formats.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tuf/formats.py b/tuf/formats.py index 8ab8e288..0de79b71 100755 --- a/tuf/formats.py +++ b/tuf/formats.py @@ -84,6 +84,13 @@ import six + +# TUF specification version. The constant should be updated when the version +# number of the specification changes. All metadata should list this version +# number. +TUF_VERSION_NUMBER = '1.0' +SPECIFICATION_VERSION_SCHEMA = SCHEMA.String() + # A datetime in 'YYYY-MM-DDTHH:MM:SSZ' ISO 8601 format. The "Z" zone designator # for the zero UTC offset is always used (i.e., a numerical offset is not # supported.) Example: '2015-10-21T13:20:00Z'. Note: This is a simple format @@ -247,6 +254,7 @@ ROOT_SCHEMA = SCHEMA.Object( object_name = 'ROOT_SCHEMA', _type = SCHEMA.String('Root'), + spec_version = SPECIFICATION_VERSION_SCHEMA, version = METADATAVERSION_SCHEMA, consistent_snapshot = BOOLEAN_SCHEMA, compression_algorithms = COMPRESSIONS_SCHEMA, @@ -258,6 +266,7 @@ TARGETS_SCHEMA = SCHEMA.Object( object_name = 'TARGETS_SCHEMA', _type = SCHEMA.String('Targets'), + spec_version = SPECIFICATION_VERSION_SCHEMA, version = METADATAVERSION_SCHEMA, expires = ISO8601_DATETIME_SCHEMA, targets = FILEDICT_SCHEMA, @@ -268,6 +277,7 @@ SNAPSHOT_SCHEMA = SCHEMA.Object( object_name = 'SNAPSHOT_SCHEMA', _type = SCHEMA.String('Snapshot'), + spec_version = SPECIFICATION_VERSION_SCHEMA, version = tuf.ssl_crypto.formats.METADATAVERSION_SCHEMA, expires = tuf.ssl_crypto.formats.ISO8601_DATETIME_SCHEMA, meta = FILEINFODICT_SCHEMA) @@ -276,6 +286,7 @@ TIMESTAMP_SCHEMA = SCHEMA.Object( object_name = 'TIMESTAMP_SCHEMA', _type = SCHEMA.String('Timestamp'), + spec_version = SPECIFICATION_VERSION_SCHEMA, version = tuf.ssl_crypto.formats.METADATAVERSION_SCHEMA, expires = tuf.ssl_crypto.formats.ISO8601_DATETIME_SCHEMA, meta = tuf.ssl_crypto.formats.FILEDICT_SCHEMA) @@ -342,6 +353,7 @@ def from_metadata(object): @staticmethod def make_metadata(version, expiration_date, filedict): result = {'_type' : 'Timestamp'} + result['spec_version'] = TUF_VERSION_NUMBER result['version'] = version result['expires'] = expiration_date result['meta'] = filedict @@ -387,6 +399,7 @@ def from_metadata(object): def make_metadata(version, expiration_date, keydict, roledict, consistent_snapshot, compression_algorithms): result = {'_type' : 'Root'} + result['spec_version'] = TUF_VERSION_NUMBER result['version'] = version result['expires'] = expiration_date result['keys'] = keydict @@ -427,6 +440,7 @@ def from_metadata(object): @staticmethod def make_metadata(version, expiration_date, versiondict): result = {'_type' : 'Snapshot'} + result['spec_version'] = TUF_VERSION_NUMBER result['version'] = version result['expires'] = expiration_date result['meta'] = versiondict @@ -474,6 +488,7 @@ def make_metadata(version, expiration_date, filedict=None, delegations=None): ' empty targets metadata.') result = {'_type' : 'Targets'} + result['spec_version'] = TUF_VERSION_NUMBER result['version'] = version result['expires'] = expiration_date result['targets'] = {} From ea63aafec6145be29d929d21c085b9f6de3949f9 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Thu, 1 Dec 2016 11:24:14 -0500 Subject: [PATCH 02/24] Use SCHEMA.AnyString() rather than SCHEMA.String('') Also update test_formats.py --- tests/test_formats.py | 135 ++++++++++++++++++++++-------------------- tuf/formats.py | 2 +- 2 files changed, 71 insertions(+), 66 deletions(-) diff --git a/tests/test_formats.py b/tests/test_formats.py index b9d9d780..8e774c9a 100755 --- a/tests/test_formats.py +++ b/tests/test_formats.py @@ -54,94 +54,94 @@ def test_schemas(self): '1985-10-21T13:20:00Z'), 'UNIX_TIMESTAMP_SCHEMA': (tuf.ssl_crypto.formats.UNIX_TIMESTAMP_SCHEMA, 499137720), - + 'HASH_SCHEMA': (tuf.ssl_crypto.formats.HASH_SCHEMA, 'A4582BCF323BCEF'), - + 'HASHDICT_SCHEMA': (tuf.ssl_crypto.formats.HASHDICT_SCHEMA, {'sha256': 'A4582BCF323BCEF'}), - + 'HEX_SCHEMA': (tuf.ssl_crypto.formats.HEX_SCHEMA, 'A4582BCF323BCEF'), - + 'KEYID_SCHEMA': (tuf.ssl_crypto.formats.KEYID_SCHEMA, '123456789abcdef'), - + 'KEYIDS_SCHEMA': (tuf.ssl_crypto.formats.KEYIDS_SCHEMA, ['123456789abcdef', '123456789abcdef']), - + 'SIG_METHOD_SCHEMA': (tuf.ssl_crypto.formats.SIG_METHOD_SCHEMA, 'ed25519'), - + 'RELPATH_SCHEMA': (tuf.ssl_crypto.formats.RELPATH_SCHEMA, 'metadata/root/'), - + 'RELPATHS_SCHEMA': (tuf.ssl_crypto.formats.RELPATHS_SCHEMA, ['targets/role1/', 'targets/role2/']), - + 'PATH_SCHEMA': (tuf.ssl_crypto.formats.PATH_SCHEMA, '/home/someuser/'), - + 'PATHS_SCHEMA': (tuf.ssl_crypto.formats.PATHS_SCHEMA, ['/home/McFly/', '/home/Tannen/']), - + 'URL_SCHEMA': (tuf.ssl_crypto.formats.URL_SCHEMA, 'https://www.updateframework.com/'), - + 'VERSION_SCHEMA': (tuf.ssl_crypto.formats.VERSION_SCHEMA, {'major': 1, 'minor': 0, 'fix': 8}), - + 'LENGTH_SCHEMA': (tuf.ssl_crypto.formats.LENGTH_SCHEMA, 8), - + 'NAME_SCHEMA': (tuf.ssl_crypto.formats.NAME_SCHEMA, 'Marty McFly'), - + 'BOOLEAN_SCHEMA': (tuf.ssl_crypto.formats.BOOLEAN_SCHEMA, True), - + 'THRESHOLD_SCHEMA': (tuf.ssl_crypto.formats.THRESHOLD_SCHEMA, 1), - + 'ROLENAME_SCHEMA': (tuf.ssl_crypto.formats.ROLENAME_SCHEMA, 'Root'), - + 'RSAKEYBITS_SCHEMA': (tuf.ssl_crypto.formats.RSAKEYBITS_SCHEMA, 4096), - + 'PASSWORD_SCHEMA': (tuf.ssl_crypto.formats.PASSWORD_SCHEMA, 'secret'), - + 'PASSWORDS_SCHEMA': (tuf.ssl_crypto.formats.PASSWORDS_SCHEMA, ['pass1', 'pass2']), - + 'KEYVAL_SCHEMA': (tuf.ssl_crypto.formats.KEYVAL_SCHEMA, {'public': 'pubkey', 'private': 'privkey'}), - + 'KEY_SCHEMA': (tuf.ssl_crypto.formats.KEY_SCHEMA, {'keytype': 'rsa', 'keyval': {'public': 'pubkey', 'private': 'privkey'}}), - + 'RSAKEY_SCHEMA': (tuf.ssl_crypto.formats.RSAKEY_SCHEMA, {'keytype': 'rsa', 'keyid': '123456789abcdef', 'keyval': {'public': 'pubkey', 'private': 'privkey'}}), - + 'FILEINFO_SCHEMA': (tuf.ssl_crypto.formats.FILEINFO_SCHEMA, {'length': 1024, 'hashes': {'sha256': 'A4582BCF323BCEF'}, 'custom': {'type': 'paintjob'}}), - + 'FILEDICT_SCHEMA': (tuf.ssl_crypto.formats.FILEDICT_SCHEMA, {'metadata/root.json': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'metadata'}}}), - + 'TARGETINFO_SCHEMA': (tuf.ssl_crypto.formats.TARGETINFO_SCHEMA, {'filepath': 'targets/target1.gif', 'fileinfo': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'target'}}}), - + 'TARGETINFOS_SCHEMA': (tuf.ssl_crypto.formats.TARGETINFOS_SCHEMA, [{'filepath': 'targets/target1.gif', 'fileinfo': {'length': 1024, 'hashes': {'sha256': 'ABCD123'}, 'custom': {'type': 'target'}}}]), - + 'SIGNATURE_SCHEMA': (tuf.ssl_crypto.formats.SIGNATURE_SCHEMA, {'keyid': '123abc', 'method': 'evp', 'sig': 'A4582BCF323BCEF'}), - + 'SIGNATURESTATUS_SCHEMA': (tuf.ssl_crypto.formats.SIGNATURESTATUS_SCHEMA, {'threshold': 1, 'good_sigs': ['123abc'], @@ -149,13 +149,13 @@ def test_schemas(self): 'unknown_sigs': ['123abc'], 'untrusted_sigs': ['123abc'], 'unknown_method_sigs': ['123abc']}), - + 'SIGNABLE_SCHEMA': (tuf.ssl_crypto.formats.SIGNABLE_SCHEMA, {'signed': 'signer', 'signatures': [{'keyid': '123abc', 'method': 'evp', 'sig': 'A4582BCF323BCEF'}]}), - + 'KEYDICT_SCHEMA': (tuf.ssl_crypto.formats.KEYDICT_SCHEMA, {'123abc': {'keytype': 'rsa', 'keyval': {'public': 'pubkey', @@ -166,7 +166,7 @@ def test_schemas(self): 'keyid': '123456789abcdef', 'keyval': {'public': 'pubkey', 'private': 'privkey'}}}), - + 'SCPCONFIG_SCHEMA': (tuf.ssl_crypto.formats.SCPCONFIG_SCHEMA, {'general': {'transfer_module': 'scp', 'metadata_path': '/path/meta.json', @@ -196,6 +196,7 @@ def test_schemas(self): 'ROOT_SCHEMA': (tuf.ssl_crypto.formats.ROOT_SCHEMA, {'_type': 'Root', + 'spec_version': '1.0', 'version': 8, 'consistent_snapshot': False, 'compression_algorithms': ['gz'], @@ -209,6 +210,7 @@ def test_schemas(self): 'TARGETS_SCHEMA': (tuf.ssl_crypto.formats.TARGETS_SCHEMA, {'_type': 'Targets', + 'spec_version': '1.0', 'version': 8, 'expires': '1985-10-21T13:20:00Z', 'targets': {'metadata/targets.json': {'length': 1024, @@ -223,12 +225,14 @@ def test_schemas(self): 'SNAPSHOT_SCHEMA': (tuf.formats.SNAPSHOT_SCHEMA, {'_type': 'Snapshot', + 'spec_version': '1.0', 'version': 8, 'expires': '1985-10-21T13:20:00Z', 'meta': {'snapshot.json': {'version': 1024}}}), 'TIMESTAMP_SCHEMA': (tuf.formats.TIMESTAMP_SCHEMA, {'_type': 'Timestamp', + 'spec_version': '1.0', 'version': 8, 'expires': '1985-10-21T13:20:00Z', 'meta': {'metadattimestamp.json': {'length': 1024, @@ -251,24 +255,25 @@ def test_schemas(self): 'MIRRORLIST_SCHEMA': (tuf.ssl_crypto.formats.MIRRORLIST_SCHEMA, {'_type': 'Mirrors', 'version': 8, + 'spec_version': '1.0', 'expires': '1985-10-21T13:20:00Z', 'mirrors': [{'url_prefix': 'http://localhost:8001', 'metadata_path': 'metadata/', 'targets_path': 'targets/', 'confined_target_dirs': ['path1/', 'path2/'], 'custom': {'type': 'mirror'}}]})} - + # Iterate 'valid_schemas', ensuring each 'valid_schema' correctly matches # its respective 'schema_type'. for schema_name, (schema_type, valid_schema) in six.iteritems(valid_schemas): self.assertEqual(True, schema_type.matches(valid_schema)) - + # Test conditions for invalid schemas. # Set the 'valid_schema' of 'valid_schemas' to an invalid # value and test that it does not match 'schema_type'. for schema_name, (schema_type, valid_schema) in six.iteritems(valid_schemas): invalid_schema = 0xBAD - if isinstance(schema_type, tuf.ssl_commons.schema.Integer): + if isinstance(schema_type, tuf.ssl_commons.schema.Integer): invalid_schema = 'BAD' self.assertEqual(False, schema_type.matches(invalid_schema)) @@ -282,16 +287,16 @@ def __init__(self, version, expires): self.info = {} self.info['version'] = version self.info['expires'] = expires - + metadata = NewMetadataFile(123, 456) metadata2 = NewMetadataFile(123, 456) metadata3 = NewMetadataFile(333, 333) # Test the comparison operators. self.assertTrue(metadata == metadata2) - self.assertFalse(metadata != metadata2) + self.assertFalse(metadata != metadata2) self.assertFalse(metadata == metadata3) - + # Test the 'getattr' method. self.assertEqual(123, getattr(metadata, 'version')) self.assertRaises(AttributeError, getattr, metadata, 'bad') @@ -300,7 +305,7 @@ def __init__(self, version, expires): def test_TimestampFile(self): # Test conditions for valid instances of 'tuf.formats.TimestampFile'. - version = 8 + version = 8 length = 88 hashes = {'sha256': '3c7fe3eeded4a34'} expires = '1985-10-21T13:20:00Z' @@ -325,7 +330,7 @@ def test_TimestampFile(self): bad_expires, filedict) self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_metadata, version, expires, bad_filedict) - + self.assertRaises(tuf.ssl_commons.exceptions.FormatError, from_metadata, 123) @@ -344,7 +349,7 @@ def test_RootFile(self): roledict = {'root': {'keyids': ['123abc'], 'threshold': 1, 'paths': ['path1/', 'path2']}} - + compression_algorithms = ['gz'] make_metadata = tuf.formats.RootFile.make_metadata @@ -396,7 +401,7 @@ def test_SnapshotFile(self): version = 8 expires = '1985-10-21T13:20:00Z' versiondict = {'targets.json' : {'version': version}} - + make_metadata = tuf.formats.SnapshotFile.make_metadata from_metadata = tuf.formats.SnapshotFile.from_metadata SNAPSHOT_SCHEMA = tuf.formats.SNAPSHOT_SCHEMA @@ -412,11 +417,11 @@ def test_SnapshotFile(self): bad_versiondict = 123 self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_metadata, version, expires, bad_versiondict) - self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_metadata, bad_version, expires, + self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_metadata, bad_version, expires, versiondict) self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_metadata, version, bad_expires, bad_versiondict) - + self.assertRaises(tuf.ssl_commons.exceptions.FormatError, from_metadata, 123) @@ -446,15 +451,15 @@ def test_TargetsFile(self): metadata = make_metadata(version, expires, filedict, delegations) self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.TargetsFile)) - + # Test conditions for different combination of required arguments (i.e., # a filedict or delegations argument is required.) metadata = make_metadata(version, expires, filedict) self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.TargetsFile)) - + metadata = make_metadata(version, expires, delegations=delegations) self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.TargetsFile)) - + # Directly instantiating a TargetsFile object. tuf.formats.TargetsFile(version, expires) tuf.formats.TargetsFile(version, expires, filedict) @@ -476,16 +481,16 @@ def test_TargetsFile(self): self.assertRaises(tuf.ssl_commons.exceptions.Error, make_metadata, version, expires) self.assertRaises(tuf.ssl_commons.exceptions.FormatError, from_metadata, 123) - + def test_MirrorsFile(self): # Test normal case. version = 8 expires = '1985-10-21T13:20:00Z' - + mirrors_file = tuf.formats.MirrorsFile(version, expires) - + make_metadata = tuf.formats.MirrorsFile.make_metadata from_metadata = tuf.formats.MirrorsFile.from_metadata @@ -496,7 +501,7 @@ def test_MirrorsFile(self): def test_unix_timestamp_to_datetime(self): # Test conditions for valid arguments. - UNIX_TIMESTAMP_SCHEMA = tuf.ssl_crypto.formats.UNIX_TIMESTAMP_SCHEMA + UNIX_TIMESTAMP_SCHEMA = tuf.ssl_crypto.formats.UNIX_TIMESTAMP_SCHEMA self.assertTrue(datetime.datetime, tuf.formats.unix_timestamp_to_datetime(499137720)) datetime_object = datetime.datetime(1985, 10, 26, 1, 22) self.assertEqual(datetime_object, tuf.formats.unix_timestamp_to_datetime(499137720)) @@ -565,22 +570,22 @@ def test_make_signable(self): self.assertTrue(SIGNABLE_SCHEMA.matches(tuf.ssl_crypto.formats.make_signable(root))) signable = tuf.ssl_crypto.formats.make_signable(root) self.assertEqual('root', tuf.formats.check_signable_object_format(signable)) - + self.assertEqual(signable, tuf.ssl_crypto.formats.make_signable(signable)) - # Test conditions for miscellaneous arguments. + # Test conditions for miscellaneous arguments. self.assertTrue(SIGNABLE_SCHEMA.matches(tuf.ssl_crypto.formats.make_signable('123'))) self.assertTrue(SIGNABLE_SCHEMA.matches(tuf.ssl_crypto.formats.make_signable(123))) def test_make_fileinfo(self): - # Test conditions for valid arguments. + # Test conditions for valid arguments. length = 1024 hashes = {'sha256': 'A4582BCF323BCEF', 'sha512': 'A4582BCF323BFEF'} version = 8 custom = {'type': 'paintjob'} - + FILEINFO_SCHEMA = tuf.ssl_crypto.formats.FILEINFO_SCHEMA make_fileinfo = tuf.formats.make_fileinfo self.assertTrue(FILEINFO_SCHEMA.matches(make_fileinfo(length, hashes, version, custom))) @@ -598,9 +603,9 @@ def test_make_fileinfo(self): self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_fileinfo, length, bad_hashes) - + def test_make_versioninfo(self): - # Test conditions for valid arguments. + # Test conditions for valid arguments. version_number = 8 versioninfo = {'version': version_number} @@ -612,11 +617,11 @@ def test_make_versioninfo(self): bad_version_number = '8' self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_versioninfo, bad_version_number) - + def test_make_role_metadata(self): - # Test conditions for valid arguments. + # Test conditions for valid arguments. keyids = ['123abc', 'abc123'] threshold = 2 paths = ['path1/', 'path2'] @@ -632,7 +637,7 @@ def test_make_role_metadata(self): self.assertTrue(ROLE_SCHEMA.matches(make_role(keyids, threshold, name=name, paths=paths))) self.assertTrue(ROLE_SCHEMA.matches(make_role(keyids, threshold, name=name, path_hash_prefixes=path_hash_prefixes))) - + # Test conditions for invalid arguments. bad_keyids = 'bad' bad_threshold = 'bad' @@ -654,14 +659,14 @@ def test_make_role_metadata(self): self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_role, keyids, bad_threshold, name=name, paths=paths) self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_role, keyids, threshold, name=bad_name, paths=paths) self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_role, keyids, threshold, name=name, paths=bad_paths) - + # 'paths' and 'path_hash_prefixes' cannot both be specified. self.assertRaises(tuf.ssl_commons.exceptions.FormatError, make_role, keyids, threshold, name, paths, path_hash_prefixes) def test_get_role_class(self): # Test conditions for valid arguments. get_role_class = tuf.formats.get_role_class - + self.assertEqual(tuf.formats.RootFile, get_role_class('Root')) self.assertEqual(tuf.formats.TargetsFile, get_role_class('Targets')) self.assertEqual(tuf.formats.SnapshotFile, get_role_class('Snapshot')) @@ -709,7 +714,7 @@ def test_check_signable_object_format(self): 'roles': {'root': {'keyids': ['123abc'], 'threshold': 1, 'paths': ['path1/', 'path2']}}} - + root = tuf.ssl_crypto.formats.make_signable(root) self.assertEqual('root', tuf.formats.check_signable_object_format(root)) @@ -737,7 +742,7 @@ def test_check_signable_object_format(self): def test_encode_canonical(self): # Test conditions for valid arguments. encode = tuf.ssl_crypto.formats.encode_canonical - result = [] + result = [] output = result.append bad_output = 123 @@ -747,7 +752,7 @@ def test_encode_canonical(self): self.assertEqual('[]', encode([])) self.assertEqual('{"A":[99]}', encode({"A": [99]})) self.assertEqual('{"x":3,"y":2}', encode({"x": 3, "y": 2})) - + self.assertEqual('{"x":3,"y":null}', encode({"x": 3, "y": None})) # Condition where 'encode()' sends the result to the callable diff --git a/tuf/formats.py b/tuf/formats.py index 0de79b71..eabb85ca 100755 --- a/tuf/formats.py +++ b/tuf/formats.py @@ -89,7 +89,7 @@ # number of the specification changes. All metadata should list this version # number. TUF_VERSION_NUMBER = '1.0' -SPECIFICATION_VERSION_SCHEMA = SCHEMA.String() +SPECIFICATION_VERSION_SCHEMA = SCHEMA.AnyString() # A datetime in 'YYYY-MM-DDTHH:MM:SSZ' ISO 8601 format. The "Z" zone designator # for the zero UTC offset is always used (i.e., a numerical offset is not From 2bfc7994390e91e034b307f35b4ba7d378a9e6ba Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Thu, 1 Dec 2016 11:28:42 -0500 Subject: [PATCH 03/24] Add test metadata that includes the spec version number --- .../client/metadata/current/1.root.json | Bin 0 -> 3354 bytes .../client/metadata/current/1.root.json.gz | Bin 0 -> 1680 bytes .../client/metadata/current/role1.json | Bin 1224 -> 1249 bytes .../client/metadata/current/role1.json.gz | Bin 619 -> 630 bytes .../client/metadata/current/role2.json | Bin 438 -> 463 bytes .../client/metadata/current/role2.json.gz | Bin 302 -> 312 bytes .../client/metadata/current/root.json | Bin 3329 -> 3354 bytes .../client/metadata/current/snapshot.json | Bin 678 -> 703 bytes .../client/metadata/current/snapshot.json.gz | Bin 387 -> 396 bytes .../client/metadata/current/targets.json | Bin 1597 -> 1622 bytes .../client/metadata/current/targets.json.gz | Bin 816 -> 826 bytes .../client/metadata/current/timestamp.json | Bin 554 -> 579 bytes .../client/metadata/current/timestamp.json.gz | Bin 366 -> 381 bytes .../client/metadata/previous/1.root.json | Bin 0 -> 3354 bytes .../client/metadata/previous/1.root.json.gz | Bin 0 -> 1680 bytes .../client/metadata/previous/role1.json | Bin 1224 -> 1249 bytes .../client/metadata/previous/role1.json.gz | Bin 619 -> 630 bytes .../client/metadata/previous/role2.json | Bin 438 -> 463 bytes .../client/metadata/previous/role2.json.gz | Bin 302 -> 312 bytes .../client/metadata/previous/root.json | Bin 3329 -> 3354 bytes .../client/metadata/previous/snapshot.json | Bin 678 -> 703 bytes .../client/metadata/previous/snapshot.json.gz | Bin 387 -> 396 bytes .../client/metadata/previous/targets.json | Bin 1597 -> 1622 bytes .../client/metadata/previous/targets.json.gz | Bin 816 -> 826 bytes .../client/metadata/previous/timestamp.json | Bin 554 -> 579 bytes .../metadata/previous/timestamp.json.gz | Bin 366 -> 381 bytes .../repository/metadata.staged/1.root.json | Bin 3329 -> 3354 bytes .../repository/metadata.staged/role1.json | Bin 1224 -> 1249 bytes .../repository/metadata.staged/role1.json.gz | Bin 619 -> 630 bytes .../repository/metadata.staged/role2.json | Bin 438 -> 463 bytes .../repository/metadata.staged/role2.json.gz | Bin 302 -> 312 bytes .../repository/metadata.staged/root.json | Bin 3329 -> 3354 bytes .../repository/metadata.staged/snapshot.json | Bin 678 -> 703 bytes .../metadata.staged/snapshot.json.gz | Bin 387 -> 396 bytes .../repository/metadata.staged/targets.json | Bin 1597 -> 1622 bytes .../metadata.staged/targets.json.gz | Bin 816 -> 826 bytes .../repository/metadata.staged/timestamp.json | Bin 554 -> 579 bytes .../metadata.staged/timestamp.json.gz | Bin 366 -> 381 bytes .../repository/metadata/1.root.json | Bin 3329 -> 3354 bytes .../repository/metadata/role1.json | Bin 1224 -> 1249 bytes .../repository/metadata/role1.json.gz | Bin 619 -> 630 bytes .../repository/metadata/role2.json | Bin 438 -> 463 bytes .../repository/metadata/role2.json.gz | Bin 302 -> 312 bytes .../repository/metadata/root.json | Bin 3329 -> 3354 bytes .../repository/metadata/snapshot.json | Bin 678 -> 703 bytes .../repository/metadata/snapshot.json.gz | Bin 387 -> 396 bytes .../repository/metadata/targets.json | Bin 1597 -> 1622 bytes .../repository/metadata/targets.json.gz | Bin 816 -> 826 bytes .../repository/metadata/timestamp.json | Bin 554 -> 579 bytes .../repository/metadata/timestamp.json.gz | Bin 366 -> 381 bytes 50 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/repository_data/client/metadata/current/1.root.json create mode 100644 tests/repository_data/client/metadata/current/1.root.json.gz create mode 100644 tests/repository_data/client/metadata/previous/1.root.json create mode 100644 tests/repository_data/client/metadata/previous/1.root.json.gz diff --git a/tests/repository_data/client/metadata/current/1.root.json b/tests/repository_data/client/metadata/current/1.root.json new file mode 100644 index 0000000000000000000000000000000000000000..27ff6595124ca68bff53cc1e829ae57bb2de30f3 GIT binary patch literal 3354 zcmc&$+iv1m7JaX;K)hyZIQL6Q^I$HafRGSKQVE?=bgtk4wu4CmwCdk`8&WmZ)2-=} zGEyTW+2`2%?8{nf?_WRE>Sa31%;tF=%KE3;FCS{PU*TV?FTyVMuu|s&k;r^R&J$q? z#v~#|sl_fR&!e-JYc4s{0()u@i&R>zFb~89&k?Qv<6v(UHuL;oa6CySljP%QGI`qq z52}MO;S?z)1<}rVOFh!aJH!n0Sg;@!qgGnQI7gCbj%^SaP8MEhMhRn1(@0Pd#&GV5 z(a|F96;V|9pg9YcNgGup*o5FXB3=X$f)|KkM{vNH1x6LOTEg4R8sUjDh-e*+#xz8Z zvDd_sNP;Gssz|LuB2b15Js2XA8f(B=ZzAznV@-^+#ss3I#!~VawPqY1AW4+a=#>hN zDIO8B$T>riVI(RpwV)DVrh@`Ik_yWmk?Krl=r89ewQsfAd$Ba~UNSDj@e3YtkStwTt8AA|8s zJ17|f7%>@z3(Px@tfPWr6bR;UDWL^4Optxe?9eDEfL+#(dmjfw7#g>YU^@q)_2o*)fdA>Q2rtb1p0hBG%JbN(9S-ws; z^VK&7*Xpx3!^ zG7oc8&i^C|@V%TH!o^W1j*lFZDzvxYU=2L`mY(1V=UBhJUhTY?<@dvC_2StsQwIz6 zpsXj_1NI09)dFw1As{YZ9qPdYfEFYL!t&aK>;TP)iB=2cEDA;)U4Uvq$&UI)BhpbY zp$vzj2ZN|!22cYCmc%PCr6l*!TfzX1!FdW`k|1opVu{1w-8?Gq-;fhdKqrY}0x6JI zfVeWCpUO$cy@E7oC@__jgbLUa$_|nW!UAo;S_gdmV@}@PI^F>H|HjF>G(UlnkJYc) z>GsZRqwD5buT>j#?hcFh*|67Z=8wsFbGCSzFVe1lMa|^0bDAUjK6)qXk~zkyCg(S&82Xyn6KcN!bIYoAN+N0aS#``YU_WUv2xDo6NkhrSfk`)n}`cZ$w+MtVN$+@&Y$!rQa{ z=+ev6;+bsMKB1@i;!!0pt-`IgnL6*?PM-%SCu`N%mYw@7xjv)l^JnR2HyKCCiyxVO z_LN+Vujs|n*e|F((8b!l4zk@onGKss()rhYb^uf7y#3$!`XiGJG6*Ixn7m-Nh|)xl zgB8%0WYzYmR?-*=5=0bY3??2JfnfUJS|Z^L*7omL7bIXB0&&sMOeyt3aSU1+l+!8( zn9r~W{ZSBwfGw*mL||3GFeDg)rF#?oqvC?>9#pr!&XqB%dA_WgH2$Fv{Lo?#UcG78kB+>%eg2dq8?&B;&G)ALCw{yeR6plOx(emS rtcw3pns+zPzwiXMkANwQ;2vJWx|*B7pE~|0I?gx$S%YGJ{qXfS4+N7Q literal 0 HcmV?d00001 diff --git a/tests/repository_data/client/metadata/current/1.root.json.gz b/tests/repository_data/client/metadata/current/1.root.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..4a13f7efd616dff425bc51ec67ad3e32a6f7402b GIT binary patch literal 1680 zcmV;B25SwF5qS^rY|=RvLZ8~keZ zdDx~NM(SK35}A+4c_J*qm_(!~wb%vad34rt%_V1AU{4KVkxHu-=7G52IimGXdwa{U zp5=Rk7vp3+PCk#u{VNbQ~C!Ydk(K>`IyJ*V7D z#JxdEI3lpdL0AVCgtguWO%ZogVd1djN^#4SiyS+KWAIKRVR*0s1xk&uicrkBXUKXQ zV0DnvfiX##6%fBA&S;4c>;(>3BM`+B+32a@!C+5#2r_CRuwu$!7P-bk2^|rN@BuZ3 zIm?7H%m=}wwUHohwTRjnqeo0dmMi z;F=ljL;#eC44PSuxTJ)5K~a>*Y3dO6kUZoF&TS`#i= z@X=_>ttEyyYmAVb5+{xE;3-$ca!54h4id$M^b-8FhAQVIqd~%_+G;?90J01~k4(Ux z3?Q~b1VJ@cS}>-y@){W;6_YR;l<@&Djmjxwz`8M8;tS%LOd<-XdjW z2%aK`wRT!M1qFzzoun6nX>iyQEipk5H}%>I$deIFAtF5I#6k&KD=U8)$BcMcem*PEibmaYuejgo$qG%4=S6@ zQ8dF6cB35=t8Ugo<*}C#MUfSw;n*d(81{D0Lwu2s#w=S;(xQjm zLJ#Hf@LVkC%|bQWr-RmmX@5;O{Rh*XeqGIGgS%|jYvARsxk!hDReHJ^4aTkR_2O*a zI4>q~eYnN3WTZsxq36xBqh@|Marw>3?M3FMdQ1~?mu)tU`%9slYmme=nLK2LjAD2= z+2vPh9EXL;Pvm*;cG~F9JBve0JDX?K?uW1Gp-X=d*q#?#&~bk>X5 z;H`YSDv2nzN3o&1_ObMSG~R4B&%J&__WF-Ua)fWU=xZ^#%jUyytLRK;r028FZF;yW zygliU&b>S;9?53q6MB@-?^W{DD%^6Dsng!genstpE>`Y&kZpI#bl6Oi&Oh$5eKB=T+y7o)e`b<_GY`-R=;KX{ z(nODg70`+$9Elj!3YxP72_gzHrl6ZtoF`mYJZ_W4VWtj%f~*5zOL@!_KSH9yj2DA#6L{DmhUZl3?c alb;3i6js%d>2>1e;N^EOHy%3y4FCXs~>mizbg1 tLWX9Fh(@GQS%{p-BtcOa`n(?Qi_LVkc6``vI$h4=emjO8%+KXv_yd9rE?)ou delta 146 zcmWN_u@%BF35dq zEN<*6>6nNnU4se+vkaaTg}|0d-hCE?0*l26tGg%?sFTFb;7UV_rk(<$SJ8Bh)|AyM U>ZpyX&7e(>+xEB|pX+`518V;$PXGV_ diff --git a/tests/repository_data/client/metadata/current/role1.json.gz b/tests/repository_data/client/metadata/current/role1.json.gz index e2fd36f00b5d950d4b88ee2ee8286bc891929560..a1ba3cc4f6ef413fd6eef22bc180cb823fc354b6 100644 GIT binary patch literal 630 zcmV-+0*U<}iwFQiN{iHwc8Nf5h5iz5F% z`I2Pa>jub%L=wE5bNIR0Hbb}D)A)Mgp?TQ;+-$d>_1iYT_@gV;(hxWcg0U2K+JMg4 zFlP*;vU7syusE%w(T1R!G=-qZgv6!9lqoiMbG{cI+rylY3tFo#_F8_fq9rSI-bcWa zGoWLK0j&w_IHLAqT~iM;sZo5Nvv`x3Q#MJxkv)>1 zKt#4S=-|AyVl8_E6rePzma&GYzi}j(O*YNwXTUM$;(C`gZJ&ynn^ZBueXgG3ye&f?nWi&;qdsrOfDz%HUzDw7$ zz8~Mmo4zJF@bHI9RuN2jjFPHrvDyb!R3>Zc##o>VR!-H$#$;3!V-P|L1eS<0W&jMq zr7I?@jwZo~O-w?{fl(=!Qc3r!?v8LOCR7c$T&xkV>&Dg_nF88oh~7pAp|EkDJZ0cy zgSWZ>8Y~jL&KfL-BvKdJSVNULF~$TCWm$-8`?u|E*KWZrm^oz56Q+pVO9-NLk8v=aQeM%e2+ia}~KwJXKfb-gCUv^g6 z){xK9Cq%D28*AJQh(iM3lx8kf{rs>oB6F)V6V1!?agw>kCqD0F8kfGCB!ldD>W_zU zOI#?s9sUDv*GiifFCCBF3lF>Fxu3fIRjnmq>{yds8QspLbh93xAMRzYSUzd6UcK>f zf3j{)uVLupoNIzoy3i^*1y;yfvIZ1FEnZN0(%yua4WPC}Vp1z8nK+9nQOjE!m+JPv ztkR#4gWO?!0{aQwKQs9k4+q{aB+T#Y8wDqxy5-qh-X!OJUuL5}%ofc&jB>l`%Di;P zVRnhS1ADGEaE-j5`gNol4F3zD}XjWauKg_Uc zT?#8yxkboiTBnkVOc)#!aN#6|awUjSEB4-H*6es53XVDgXy=+Xmis0Kac;J$tZMo$L63De=%Gjb#*|jDbAaNmQ zP8tch2$T`gK~^N0rL-RttWvH1sGC6!yQwREX;*C&uk60bc`T#1l7Fc#zX8(V<;ute F0093UC;tEd diff --git a/tests/repository_data/client/metadata/current/role2.json b/tests/repository_data/client/metadata/current/role2.json index 20b1206a703a64ca9c8c92070f4e43f3c894085c..e15e356b57e447c1006facc1a34aa19e40978903 100644 GIT binary patch delta 164 zcmV~$I|>3p3;Ed*VE$n`Fy=h$K8YnSl`3`55Fugm;e9( delta 144 zcmV~$yAc9037`!ZV8%aw~*dpvQ OMbnY*%kg}Fj_V(?D<~}h diff --git a/tests/repository_data/client/metadata/current/role2.json.gz b/tests/repository_data/client/metadata/current/role2.json.gz index 6074f9bdfd6b611f2ac527c62c1ab56896f80073..8e7b33d88d1fce7612ef18b02e4f193373bbe6e9 100644 GIT binary patch literal 312 zcmV-80muFyiwFQiN1V&#R~H{+Pm)kDaMICG&wbR1 z5HpF*z0NkWptITpB#kjiP7ot?V9@yl#T6V%!I8onx*Vl&XqUT8w&!3&$3gql5fF<- z({-K^vWuAjRDroS?RND@L}t`E3ALN97nu<^H0)&>E4N}f%ATgf`7}NTYh?9uUp5=g z$0gJ4tX+S}@8z%rtq=^nfG)KGSl4=6q{oZo-H!}o5uYdZD=ZJw1K??){)co^=+iwFSh1KU>u|22?HZo@DPME5?0p>+ySAIf6RkyVSJpiL?@njdVpXb|M? zmF)ze78*!zhI6lKGxmowPd|f>W?O$$b$u_VHs5;dr6`6WB4kG*8hrrYbwRariES5S zb}l-J-c#^_p-7%nvK&&YBGh(FX0z~4I(=Ohpo&AZFTL2$V#?BSvKTBjO36!#np+#m zHZ0T>zLm@ka%hC8c(k6p03l|JkT_?=Hbwy?m$PGWIe05ExhN4s03ar3TVz%QpM7o! zTObt-lz~kN^Qh|m=GlnOQRgPi=XAU39C63PL8o!aZA6cH;Hkfy$LGVPvgPtvHybX; zwbT8~UViD{wO@-i4m`YpEwcmIF7v*kr>D=0WPWuRi%}75RYE@g0ng)=5VipT09=xb A4FCWD diff --git a/tests/repository_data/client/metadata/current/root.json b/tests/repository_data/client/metadata/current/root.json index ab8e8dc8598b5d2196fd1ad728ce06d1bd51f58e..27ff6595124ca68bff53cc1e829ae57bb2de30f3 100644 GIT binary patch delta 828 zcmYLHOR5z(5FH4DZwZbbZ`RN>^-WT4rl~JDQBiOvmtKI-%Y;cJjfbF@yK0f!1Xvw9 zysAy5Lw3v=Lhnums@1Ez76>L`KM)O5I zah2KT2GuL)98w(ac9v<3Xkd*~+eJh#XUU-8~NcdH4K+f5FS2PtVUUziasP{O#%64^0f@%m4rY delta 803 zcmWlXJC0T{4226MB&evT8nFUDSChIwM!Rcx9F;jC9*E-DX3+qVUAIqPHkZ3 zR$VJih_t4~p}0{CZpaC0^N>f03SFNnd%2+sNQ0dKMbQKbWfHuHA>0WUn%Ox%7q7?e z!*<3n^{PUQmN-)b%bjvgGLS@ZOol)i})*>J>-T{0#u|-_@u0Vtf5hqLaFzxn+%sa-o*Z9%C zkX-DLTEQ~B1Lz!>XdZ8++Y>0UF4`Q4^ANGuU{=FP)GcWOp^2|z+ul$P!)=wRJO7LIPQS*GO{cHeaUy>1)9 bf3NTA!>3>O$Iq|dzkUAlj31w0KEC`1zUJKA diff --git a/tests/repository_data/client/metadata/current/snapshot.json b/tests/repository_data/client/metadata/current/snapshot.json index bf565452c904a703d13ee5b27936065ab8a508e4..2b55b31b57233a20c62e3a695647bc20105b0a95 100644 GIT binary patch delta 241 zcmWm6F-k;141i(w!8X=f*vUJ9CYi}hVr4DfK_-&~wo!4x*4|2ackmjX#(TKd|HuEm z|Ji?jyl2YnM8X0Do;6HkQfZ8!Oqm1JODp6Wq6SQOiUoUmhDVNU)rPb|BQq-?wx-z` zYba2P4hl_as!nEuYLieRE8b6>VQ1Uf?)NUDsu<#E(T8LyJ<@%8W=F&l$Q>d}s43WF r{r`gYFs`alW4l={7p~j=@^F59iTU^zugAml(|UWg;x(+>*K+X(hwVfi delta 233 zcmWO0J4!@B5QSmp!Xy)!nhkEiuCD5O7#WM3sOqi;69*K`26H3f?!j%i8uwvmC-~uf zzsH~B_t&Qpm;<&bonR)mG6d>0qC&z9V@$7IgL(i#Q8nS{qSiINH4o>UbBc~Woj3r* z3LsYnPbN!9svv+fJV>$%CHNeQ>fOr$_tW9;v7i$6j!}I9kWr1+_R7g1v>YVZ8mSB> m@mR@vuEmmV0eHXPZntXt)AoGxk#FxWm)E<8Gn~%X)Ab*_wm-!H diff --git a/tests/repository_data/client/metadata/current/snapshot.json.gz b/tests/repository_data/client/metadata/current/snapshot.json.gz index 88aa0f12c90f526ce4bca0793f7d405c7e8b082b..a767bfb9e84cbaa8b8d65ed951a91dde8e736b62 100644 GIT binary patch literal 396 zcmV;70dxKziwFQiN*65xh80Er z`(!)ausv)OC_p-$j>mi5b!IvqPI>-%k;&Y5A9h{$+ID9?%geDg#9$)AP*MWuJ=Chu zmb1lTJ2TXTzK`DJ;shF)J$uT@a3IjRMD)#m7GGRtf~$WLtu>_oiLCl&LpfUFjp!i zlM6|hsMs1C-9s_W%yrj&+}{$B#p;rTd759&vRHh7%I9eq=he88@8{!|nIW+74zSe& z!2Mc}8>tPQZ#td1jL(91pQiEj26g6}T&Cj+-~wFtKbiEO%yIsMIOJ(qeQozP&XCE6 zHF00aE q{%W;20ssKmAjFFR literal 387 zcmV-}0et=+iwFSh1KU>u|BX;xZ`&{oeD|*q^qdu1Cfs*MsT^9$jH?%17 z-%C5`fbC(MKmpY0a6H~?XY72~A9?w4mf7B$FP$;3dX4=iFNa!HD~8qaD6{G zJ%klO`{Mcxp`}1vNt}WlO7NVqR7_B%FLt--eV1jNHbLoq2=I>U_!TS!g#kl#jbISe zNeTQ=h#aLD*IDdauGA_JxSUIhwWVBI77l?cM;V48<-QF}u>z#x0He>q5~&CXc}Rdm zRi{aOA^{%yjF}rdv})$knTOpi5m~LSN!YK;%Sl#?ACG*R$7$J&TX{Ymu9;cy(0y>A z^~t&Wtv+8#x-{Q(j6F|J0(Xz|bbN=5{VC`9umP|Fm)$R>|4-(${6QRf9yedtx2`j? z4{FcY?h)wAY{5pyB!*++?xNMojiAy7_zq{LMz8mxCkV$pn~-4w5*jeU~iei>C4 h(U;xdTrPax%QF9CqwdE4{o~SI-T-FEttqAg006FZytM!T diff --git a/tests/repository_data/client/metadata/current/targets.json b/tests/repository_data/client/metadata/current/targets.json index 0620bfe42a0edd920cac821b7909ca1fb47c318d..920f63eba22c770c16606961d65eb0a570fae083 100644 GIT binary patch delta 166 zcmWN{yA8rX3;<9ibSNDQpbUU)=ROY0Alv7YXaEt3mYxD3)}Tzy8q7mp{l49=dp+&} z6_qOmuADMs6^I(J#-at)q}Dp98&wwyA|<;?(vg6c!xDU8&`8ckNUm{2K@BtrX_Tlj tn+uB;DFql72$le{1selGlje2vY&X-z?Qrw!bUdH>{kF#)%*(9(Se8ITbP#rnxW= z$(nNk03$R}vDpeSn-L9n89bC-2%}|XuV@}wW)l((7`)s&q4d$oES!2^w*^ayo0 TUBt9HF>HDr+jGA@xA*=BBY-KC diff --git a/tests/repository_data/client/metadata/current/targets.json.gz b/tests/repository_data/client/metadata/current/targets.json.gz index 0753ea6945da4785543f5d99659a1b8a641a608d..3b280cb261b5158ef942bdc008ba8bfce26579b6 100644 GIT binary patch literal 826 zcmV-A1I7FwiwFQiNlaNztOn zzprLIapGckFFTkqAc`jW9v}H@vmM6$cP-svZ zNY&P&w(2YgFBpBOOi7|@qy{L!EELpxm(ZsOp{PrFxLe{q*|a+@0j=Wfvf6w4*~l)t zEDc$jgea~l_{^^PnybsDXKs|OU^7Klti|Su385hdtbr&ou|hYIia2G-R%_~j(>2oCi-(<# zy9Yfy9?$z}_w?4S#bMkj`fy=%J$r}4<#>Ph9_9_pO%Ej`bNzk2wElcN*gK3Hus7)b zH0z|%)vgcH?s%Bx zwY?{*%$zGhGN87>#os=+tOEj7BO z#;fqk%QzjMKFDYGc{t5AkK-!XAq2jly7Xc@%<8i7!@pKd&AvWM39)%sQlctJu=j&O z)kh^4t9VWTnG{%(=fLF1SYo#`RJ~HX%5om}5Sc)OXj2nQEft8-nfe+fwmv6-o(s2l%k6)##2$+Yfp~x_)C=Rj&8k>{faDW8mlC#q6-|>-1oOdJ%U!Eo zr0E}60*{$H3C@6el#G(N4`E21`4l}tGmn*{%|q7(uc1#}sgASw7)gvmE-pGQ+_-N( z<50+gkZ19}?^0hN(+eBJw0uKc}_I_fOe`6_aR$X5t{Vvo_-|Ob}Z@nl_JXQt( E0PicI3IG5A literal 816 zcmV-01JC>)iwFSh1KU>u|D{yhZW}oaefL)w^PKKdBz5a|^l2ACKuJ_=)Q$tsq-as( z-^&?KoVeKCmj%WKL{a47;URx+w!^r8e3I$qtmE)``}bzM{b|4L@Kt~8n^^_{fey7p zYSMd@-kg@;6Gk5zQ%+GNQU^@HoG6I*E~C#8LKTa;s80kz@mvf3^EY>cd$ z?TxkwSuDO!L3_>>0K5YXF-XSloT6BoQbO`6`V!bR)UMPUmZn`KgE|2ZrI$kN0wrRR zR+yS2sZb+(G{~)Etn9fGdx(R9dEIR9?^Z^1hB`AbJWM~Hb%yvw&W}2c3+|!mK_6w> zpPt6maiQ#bn0X5xI_B0i5Chd}C00!0Y6u-MU<*W<4IP+?Bqb+SnYNZom3)n~_TphD z($N%X?Hrz z@^SAK-*48c2mSuMzs%ZzK=28ieO~}RFW+Ambxo_(-juaKaSN2IzUs?3osJ(=GW$F{ z&(Owk)#VTZU%+1|-wv~gbo}sYmCo$zOR6Du?`qD}Qch^JGl=*oG?j93oa^iY#V1t~44Rk6p$FNnCs7q=QlNXLM3pU2v+7J5lIPDA7P2v)qbKOV?~eFPi*PmSjwAKz8B?w)AOvWi?CleufG5x${dzG1^@sh9F+wC diff --git a/tests/repository_data/client/metadata/current/timestamp.json b/tests/repository_data/client/metadata/current/timestamp.json index 3f44ae9773a9bac7997713a8eb7bc3f9f1f1e362..1c425c1a0fc4eaf676a96da69387f8ef51d9390e 100644 GIT binary patch delta 259 zcmYL@J4ysW6h&#As5fBRbS8+rs`oc?CsOsQ3QSZSm~5EbNN8{oZo`eZ4kJ4=y&TTD zUx)9*$NL3~GN_nh>oJ;mDW;mMl7NEKXh@-;UK6F(jX6bzVHg>eG>Usym8O8Dr5@QF zpa>GG0koi@SQ{| delta 234 zcmWNLF-inM5Jef>Xd*MyVNcLi)m7DHYQRK6VY9{DXkoxZcnvS&IgD)h(c|;q z|2ci1Zl53Kl{_+cpl$&Hykl3T)DY|U@+wSftGpQOy z^X_GSs;UxPa4_FFHlL@?OqbW2%KgIsa@A>;>$oL1`g^?WLo)~jU%u|5cF9Zrm^ogztU|L+5QFlKRbarH0!G=3e%@k77S{E+u^Q(~yw+=B~=Jz^2I6dWTF z_!O}vXKjkU^;XdJ?xZ%tjuC=uz9LmHr`_)&%XHffrJ?tb53cJsnAs6Gkq%UHg9g51 ziIF6>fF*<&190$#obqN}MIXFw#|l84JlO~YwYR{Md!m*h2lAF;q8eIGA!ACh5@L0k zRTT>~tGEh+^+v<2!}#rVG$LEntqJpedB4jR@%em_dEv`_Pj2MT{ro7+pe6gsg3hzG zPy2j%i1cbcjMVqa_j$T4pI_(O^&cJ0#PhWKJpNTTv0k?sSMUWKLS!w+TNXW+0@$1r zm53oXDvh-SCm`B^=)~facf}I}nB8$bJr@0x>&r5!Z;0tYzvXQ{?_ppA>u{+5e^`h0 MFVhk>B`N{{0R6Sa31%;tF=%KE3;FCS{PU*TV?FTyVMuu|s&k;r^R&J$q? z#v~#|sl_fR&!e-JYc4s{0()u@i&R>zFb~89&k?Qv<6v(UHuL;oa6CySljP%QGI`qq z52}MO;S?z)1<}rVOFh!aJH!n0Sg;@!qgGnQI7gCbj%^SaP8MEhMhRn1(@0Pd#&GV5 z(a|F96;V|9pg9YcNgGup*o5FXB3=X$f)|KkM{vNH1x6LOTEg4R8sUjDh-e*+#xz8Z zvDd_sNP;Gssz|LuB2b15Js2XA8f(B=ZzAznV@-^+#ss3I#!~VawPqY1AW4+a=#>hN zDIO8B$T>riVI(RpwV)DVrh@`Ik_yWmk?Krl=r89ewQsfAd$Ba~UNSDj@e3YtkStwTt8AA|8s zJ17|f7%>@z3(Px@tfPWr6bR;UDWL^4Optxe?9eDEfL+#(dmjfw7#g>YU^@q)_2o*)fdA>Q2rtb1p0hBG%JbN(9S-ws; z^VK&7*Xpx3!^ zG7oc8&i^C|@V%TH!o^W1j*lFZDzvxYU=2L`mY(1V=UBhJUhTY?<@dvC_2StsQwIz6 zpsXj_1NI09)dFw1As{YZ9qPdYfEFYL!t&aK>;TP)iB=2cEDA;)U4Uvq$&UI)BhpbY zp$vzj2ZN|!22cYCmc%PCr6l*!TfzX1!FdW`k|1opVu{1w-8?Gq-;fhdKqrY}0x6JI zfVeWCpUO$cy@E7oC@__jgbLUa$_|nW!UAo;S_gdmV@}@PI^F>H|HjF>G(UlnkJYc) z>GsZRqwD5buT>j#?hcFh*|67Z=8wsFbGCSzFVe1lMa|^0bDAUjK6)qXk~zkyCg(S&82Xyn6KcN!bIYoAN+N0aS#``YU_WUv2xDo6NkhrSfk`)n}`cZ$w+MtVN$+@&Y$!rQa{ z=+ev6;+bsMKB1@i;!!0pt-`IgnL6*?PM-%SCu`N%mYw@7xjv)l^JnR2HyKCCiyxVO z_LN+Vujs|n*e|F((8b!l4zk@onGKss()rhYb^uf7y#3$!`XiGJG6*Ixn7m-Nh|)xl zgB8%0WYzYmR?-*=5=0bY3??2JfnfUJS|Z^L*7omL7bIXB0&&sMOeyt3aSU1+l+!8( zn9r~W{ZSBwfGw*mL||3GFeDg)rF#?oqvC?>9#pr!&XqB%dA_WgH2$Fv{Lo?#UcG78kB+>%eg2dq8?&B;&G)ALCw{yeR6plOx(emS rtcw3pns+zPzwiXMkANwQ;2vJWx|*B7pE~|0I?gx$S%YGJ{qXfS4+N7Q literal 0 HcmV?d00001 diff --git a/tests/repository_data/client/metadata/previous/1.root.json.gz b/tests/repository_data/client/metadata/previous/1.root.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..4a13f7efd616dff425bc51ec67ad3e32a6f7402b GIT binary patch literal 1680 zcmV;B25SwF5qS^rY|=RvLZ8~keZ zdDx~NM(SK35}A+4c_J*qm_(!~wb%vad34rt%_V1AU{4KVkxHu-=7G52IimGXdwa{U zp5=Rk7vp3+PCk#u{VNbQ~C!Ydk(K>`IyJ*V7D z#JxdEI3lpdL0AVCgtguWO%ZogVd1djN^#4SiyS+KWAIKRVR*0s1xk&uicrkBXUKXQ zV0DnvfiX##6%fBA&S;4c>;(>3BM`+B+32a@!C+5#2r_CRuwu$!7P-bk2^|rN@BuZ3 zIm?7H%m=}wwUHohwTRjnqeo0dmMi z;F=ljL;#eC44PSuxTJ)5K~a>*Y3dO6kUZoF&TS`#i= z@X=_>ttEyyYmAVb5+{xE;3-$ca!54h4id$M^b-8FhAQVIqd~%_+G;?90J01~k4(Ux z3?Q~b1VJ@cS}>-y@){W;6_YR;l<@&Djmjxwz`8M8;tS%LOd<-XdjW z2%aK`wRT!M1qFzzoun6nX>iyQEipk5H}%>I$deIFAtF5I#6k&KD=U8)$BcMcem*PEibmaYuejgo$qG%4=S6@ zQ8dF6cB35=t8Ugo<*}C#MUfSw;n*d(81{D0Lwu2s#w=S;(xQjm zLJ#Hf@LVkC%|bQWr-RmmX@5;O{Rh*XeqGIGgS%|jYvARsxk!hDReHJ^4aTkR_2O*a zI4>q~eYnN3WTZsxq36xBqh@|Marw>3?M3FMdQ1~?mu)tU`%9slYmme=nLK2LjAD2= z+2vPh9EXL;Pvm*;cG~F9JBve0JDX?K?uW1Gp-X=d*q#?#&~bk>X5 z;H`YSDv2nzN3o&1_ObMSG~R4B&%J&__WF-Ua)fWU=xZ^#%jUyytLRK;r028FZF;yW zygliU&b>S;9?53q6MB@-?^W{DD%^6Dsng!genstpE>`Y&kZpI#bl6Oi&Oh$5eKB=T+y7o)e`b<_GY`-R=;KX{ z(nODg70`+$9Elj!3YxP72_gzHrl6ZtoF`mYJZ_W4VWtj%f~*5zOL@!_KSH9yj2DA#6L{DmhUZl3?c alb;3i6js%d>2>1e;N^EOHy%3y4FCXs~>mizbg1 tLWX9Fh(@GQS%{p-BtcOa`n(?Qi_LVkc6``vI$h4=emjO8%+KXv_yd9rE?)ou delta 146 zcmWN_u@%BF35dq zEN<*6>6nNnU4se+vkaaTg}|0d-hCE?0*l26tGg%?sFTFb;7UV_rk(<$SJ8Bh)|AyM U>ZpyX&7e(>+xEB|pX+`518V;$PXGV_ diff --git a/tests/repository_data/client/metadata/previous/role1.json.gz b/tests/repository_data/client/metadata/previous/role1.json.gz index e2fd36f00b5d950d4b88ee2ee8286bc891929560..a1ba3cc4f6ef413fd6eef22bc180cb823fc354b6 100644 GIT binary patch literal 630 zcmV-+0*U<}iwFQiN{iHwc8Nf5h5iz5F% z`I2Pa>jub%L=wE5bNIR0Hbb}D)A)Mgp?TQ;+-$d>_1iYT_@gV;(hxWcg0U2K+JMg4 zFlP*;vU7syusE%w(T1R!G=-qZgv6!9lqoiMbG{cI+rylY3tFo#_F8_fq9rSI-bcWa zGoWLK0j&w_IHLAqT~iM;sZo5Nvv`x3Q#MJxkv)>1 zKt#4S=-|AyVl8_E6rePzma&GYzi}j(O*YNwXTUM$;(C`gZJ&ynn^ZBueXgG3ye&f?nWi&;qdsrOfDz%HUzDw7$ zz8~Mmo4zJF@bHI9RuN2jjFPHrvDyb!R3>Zc##o>VR!-H$#$;3!V-P|L1eS<0W&jMq zr7I?@jwZo~O-w?{fl(=!Qc3r!?v8LOCR7c$T&xkV>&Dg_nF88oh~7pAp|EkDJZ0cy zgSWZ>8Y~jL&KfL-BvKdJSVNULF~$TCWm$-8`?u|E*KWZrm^oz56Q+pVO9-NLk8v=aQeM%e2+ia}~KwJXKfb-gCUv^g6 z){xK9Cq%D28*AJQh(iM3lx8kf{rs>oB6F)V6V1!?agw>kCqD0F8kfGCB!ldD>W_zU zOI#?s9sUDv*GiifFCCBF3lF>Fxu3fIRjnmq>{yds8QspLbh93xAMRzYSUzd6UcK>f zf3j{)uVLupoNIzoy3i^*1y;yfvIZ1FEnZN0(%yua4WPC}Vp1z8nK+9nQOjE!m+JPv ztkR#4gWO?!0{aQwKQs9k4+q{aB+T#Y8wDqxy5-qh-X!OJUuL5}%ofc&jB>l`%Di;P zVRnhS1ADGEaE-j5`gNol4F3zD}XjWauKg_Uc zT?#8yxkboiTBnkVOc)#!aN#6|awUjSEB4-H*6es53XVDgXy=+Xmis0Kac;J$tZMo$L63De=%Gjb#*|jDbAaNmQ zP8tch2$T`gK~^N0rL-RttWvH1sGC6!yQwREX;*C&uk60bc`T#1l7Fc#zX8(V<;ute F0093UC;tEd diff --git a/tests/repository_data/client/metadata/previous/role2.json b/tests/repository_data/client/metadata/previous/role2.json index 20b1206a703a64ca9c8c92070f4e43f3c894085c..e15e356b57e447c1006facc1a34aa19e40978903 100644 GIT binary patch delta 164 zcmV~$I|>3p3;Ed*VE$n`Fy=h$K8YnSl`3`55Fugm;e9( delta 144 zcmV~$yAc9037`!ZV8%aw~*dpvQ OMbnY*%kg}Fj_V(?D<~}h diff --git a/tests/repository_data/client/metadata/previous/role2.json.gz b/tests/repository_data/client/metadata/previous/role2.json.gz index 6074f9bdfd6b611f2ac527c62c1ab56896f80073..8e7b33d88d1fce7612ef18b02e4f193373bbe6e9 100644 GIT binary patch literal 312 zcmV-80muFyiwFQiN1V&#R~H{+Pm)kDaMICG&wbR1 z5HpF*z0NkWptITpB#kjiP7ot?V9@yl#T6V%!I8onx*Vl&XqUT8w&!3&$3gql5fF<- z({-K^vWuAjRDroS?RND@L}t`E3ALN97nu<^H0)&>E4N}f%ATgf`7}NTYh?9uUp5=g z$0gJ4tX+S}@8z%rtq=^nfG)KGSl4=6q{oZo-H!}o5uYdZD=ZJw1K??){)co^=+iwFSh1KU>u|22?HZo@DPME5?0p>+ySAIf6RkyVSJpiL?@njdVpXb|M? zmF)ze78*!zhI6lKGxmowPd|f>W?O$$b$u_VHs5;dr6`6WB4kG*8hrrYbwRariES5S zb}l-J-c#^_p-7%nvK&&YBGh(FX0z~4I(=Ohpo&AZFTL2$V#?BSvKTBjO36!#np+#m zHZ0T>zLm@ka%hC8c(k6p03l|JkT_?=Hbwy?m$PGWIe05ExhN4s03ar3TVz%QpM7o! zTObt-lz~kN^Qh|m=GlnOQRgPi=XAU39C63PL8o!aZA6cH;Hkfy$LGVPvgPtvHybX; zwbT8~UViD{wO@-i4m`YpEwcmIF7v*kr>D=0WPWuRi%}75RYE@g0ng)=5VipT09=xb A4FCWD diff --git a/tests/repository_data/client/metadata/previous/root.json b/tests/repository_data/client/metadata/previous/root.json index ab8e8dc8598b5d2196fd1ad728ce06d1bd51f58e..27ff6595124ca68bff53cc1e829ae57bb2de30f3 100644 GIT binary patch delta 828 zcmYLHOR5z(5FH4DZwZbbZ`RN>^-WT4rl~JDQBiOvmtKI-%Y;cJjfbF@yK0f!1Xvw9 zysAy5Lw3v=Lhnums@1Ez76>L`KM)O5I zah2KT2GuL)98w(ac9v<3Xkd*~+eJh#XUU-8~NcdH4K+f5FS2PtVUUziasP{O#%64^0f@%m4rY delta 803 zcmWlXJC0T{4226MB&evT8nFUDSChIwM!Rcx9F;jC9*E-DX3+qVUAIqPHkZ3 zR$VJih_t4~p}0{CZpaC0^N>f03SFNnd%2+sNQ0dKMbQKbWfHuHA>0WUn%Ox%7q7?e z!*<3n^{PUQmN-)b%bjvgGLS@ZOol)i})*>J>-T{0#u|-_@u0Vtf5hqLaFzxn+%sa-o*Z9%C zkX-DLTEQ~B1Lz!>XdZ8++Y>0UF4`Q4^ANGuU{=FP)GcWOp^2|z+ul$P!)=wRJO7LIPQS*GO{cHeaUy>1)9 bf3NTA!>3>O$Iq|dzkUAlj31w0KEC`1zUJKA diff --git a/tests/repository_data/client/metadata/previous/snapshot.json b/tests/repository_data/client/metadata/previous/snapshot.json index bf565452c904a703d13ee5b27936065ab8a508e4..2b55b31b57233a20c62e3a695647bc20105b0a95 100644 GIT binary patch delta 241 zcmWm6F-k;141i(w!8X=f*vUJ9CYi}hVr4DfK_-&~wo!4x*4|2ackmjX#(TKd|HuEm z|Ji?jyl2YnM8X0Do;6HkQfZ8!Oqm1JODp6Wq6SQOiUoUmhDVNU)rPb|BQq-?wx-z` zYba2P4hl_as!nEuYLieRE8b6>VQ1Uf?)NUDsu<#E(T8LyJ<@%8W=F&l$Q>d}s43WF r{r`gYFs`alW4l={7p~j=@^F59iTU^zugAml(|UWg;x(+>*K+X(hwVfi delta 233 zcmWO0J4!@B5QSmp!Xy)!nhkEiuCD5O7#WM3sOqi;69*K`26H3f?!j%i8uwvmC-~uf zzsH~B_t&Qpm;<&bonR)mG6d>0qC&z9V@$7IgL(i#Q8nS{qSiINH4o>UbBc~Woj3r* z3LsYnPbN!9svv+fJV>$%CHNeQ>fOr$_tW9;v7i$6j!}I9kWr1+_R7g1v>YVZ8mSB> m@mR@vuEmmV0eHXPZntXt)AoGxk#FxWm)E<8Gn~%X)Ab*_wm-!H diff --git a/tests/repository_data/client/metadata/previous/snapshot.json.gz b/tests/repository_data/client/metadata/previous/snapshot.json.gz index 88aa0f12c90f526ce4bca0793f7d405c7e8b082b..a767bfb9e84cbaa8b8d65ed951a91dde8e736b62 100644 GIT binary patch literal 396 zcmV;70dxKziwFQiN*65xh80Er z`(!)ausv)OC_p-$j>mi5b!IvqPI>-%k;&Y5A9h{$+ID9?%geDg#9$)AP*MWuJ=Chu zmb1lTJ2TXTzK`DJ;shF)J$uT@a3IjRMD)#m7GGRtf~$WLtu>_oiLCl&LpfUFjp!i zlM6|hsMs1C-9s_W%yrj&+}{$B#p;rTd759&vRHh7%I9eq=he88@8{!|nIW+74zSe& z!2Mc}8>tPQZ#td1jL(91pQiEj26g6}T&Cj+-~wFtKbiEO%yIsMIOJ(qeQozP&XCE6 zHF00aE q{%W;20ssKmAjFFR literal 387 zcmV-}0et=+iwFSh1KU>u|BX;xZ`&{oeD|*q^qdu1Cfs*MsT^9$jH?%17 z-%C5`fbC(MKmpY0a6H~?XY72~A9?w4mf7B$FP$;3dX4=iFNa!HD~8qaD6{G zJ%klO`{Mcxp`}1vNt}WlO7NVqR7_B%FLt--eV1jNHbLoq2=I>U_!TS!g#kl#jbISe zNeTQ=h#aLD*IDdauGA_JxSUIhwWVBI77l?cM;V48<-QF}u>z#x0He>q5~&CXc}Rdm zRi{aOA^{%yjF}rdv})$knTOpi5m~LSN!YK;%Sl#?ACG*R$7$J&TX{Ymu9;cy(0y>A z^~t&Wtv+8#x-{Q(j6F|J0(Xz|bbN=5{VC`9umP|Fm)$R>|4-(${6QRf9yedtx2`j? z4{FcY?h)wAY{5pyB!*++?xNMojiAy7_zq{LMz8mxCkV$pn~-4w5*jeU~iei>C4 h(U;xdTrPax%QF9CqwdE4{o~SI-T-FEttqAg006FZytM!T diff --git a/tests/repository_data/client/metadata/previous/targets.json b/tests/repository_data/client/metadata/previous/targets.json index 0620bfe42a0edd920cac821b7909ca1fb47c318d..920f63eba22c770c16606961d65eb0a570fae083 100644 GIT binary patch delta 166 zcmWN{yA8rX3;<9ibSNDQpbUU)=ROY0Alv7YXaEt3mYxD3)}Tzy8q7mp{l49=dp+&} z6_qOmuADMs6^I(J#-at)q}Dp98&wwyA|<;?(vg6c!xDU8&`8ckNUm{2K@BtrX_Tlj tn+uB;DFql72$le{1selGlje2vY&X-z?Qrw!bUdH>{kF#)%*(9(Se8ITbP#rnxW= z$(nNk03$R}vDpeSn-L9n89bC-2%}|XuV@}wW)l((7`)s&q4d$oES!2^w*^ayo0 TUBt9HF>HDr+jGA@xA*=BBY-KC diff --git a/tests/repository_data/client/metadata/previous/targets.json.gz b/tests/repository_data/client/metadata/previous/targets.json.gz index 0753ea6945da4785543f5d99659a1b8a641a608d..3b280cb261b5158ef942bdc008ba8bfce26579b6 100644 GIT binary patch literal 826 zcmV-A1I7FwiwFQiNlaNztOn zzprLIapGckFFTkqAc`jW9v}H@vmM6$cP-svZ zNY&P&w(2YgFBpBOOi7|@qy{L!EELpxm(ZsOp{PrFxLe{q*|a+@0j=Wfvf6w4*~l)t zEDc$jgea~l_{^^PnybsDXKs|OU^7Klti|Su385hdtbr&ou|hYIia2G-R%_~j(>2oCi-(<# zy9Yfy9?$z}_w?4S#bMkj`fy=%J$r}4<#>Ph9_9_pO%Ej`bNzk2wElcN*gK3Hus7)b zH0z|%)vgcH?s%Bx zwY?{*%$zGhGN87>#os=+tOEj7BO z#;fqk%QzjMKFDYGc{t5AkK-!XAq2jly7Xc@%<8i7!@pKd&AvWM39)%sQlctJu=j&O z)kh^4t9VWTnG{%(=fLF1SYo#`RJ~HX%5om}5Sc)OXj2nQEft8-nfe+fwmv6-o(s2l%k6)##2$+Yfp~x_)C=Rj&8k>{faDW8mlC#q6-|>-1oOdJ%U!Eo zr0E}60*{$H3C@6el#G(N4`E21`4l}tGmn*{%|q7(uc1#}sgASw7)gvmE-pGQ+_-N( z<50+gkZ19}?^0hN(+eBJw0uKc}_I_fOe`6_aR$X5t{Vvo_-|Ob}Z@nl_JXQt( E0PicI3IG5A literal 816 zcmV-01JC>)iwFSh1KU>u|D{yhZW}oaefL)w^PKKdBz5a|^l2ACKuJ_=)Q$tsq-as( z-^&?KoVeKCmj%WKL{a47;URx+w!^r8e3I$qtmE)``}bzM{b|4L@Kt~8n^^_{fey7p zYSMd@-kg@;6Gk5zQ%+GNQU^@HoG6I*E~C#8LKTa;s80kz@mvf3^EY>cd$ z?TxkwSuDO!L3_>>0K5YXF-XSloT6BoQbO`6`V!bR)UMPUmZn`KgE|2ZrI$kN0wrRR zR+yS2sZb+(G{~)Etn9fGdx(R9dEIR9?^Z^1hB`AbJWM~Hb%yvw&W}2c3+|!mK_6w> zpPt6maiQ#bn0X5xI_B0i5Chd}C00!0Y6u-MU<*W<4IP+?Bqb+SnYNZom3)n~_TphD z($N%X?Hrz z@^SAK-*48c2mSuMzs%ZzK=28ieO~}RFW+Ambxo_(-juaKaSN2IzUs?3osJ(=GW$F{ z&(Owk)#VTZU%+1|-wv~gbo}sYmCo$zOR6Du?`qD}Qch^JGl=*oG?j93oa^iY#V1t~44Rk6p$FNnCs7q=QlNXLM3pU2v+7J5lIPDA7P2v)qbKOV?~eFPi*PmSjwAKz8B?w)AOvWi?CleufG5x${dzG1^@sh9F+wC diff --git a/tests/repository_data/client/metadata/previous/timestamp.json b/tests/repository_data/client/metadata/previous/timestamp.json index 3f44ae9773a9bac7997713a8eb7bc3f9f1f1e362..1c425c1a0fc4eaf676a96da69387f8ef51d9390e 100644 GIT binary patch delta 259 zcmYL@J4ysW6h&#As5fBRbS8+rs`oc?CsOsQ3QSZSm~5EbNN8{oZo`eZ4kJ4=y&TTD zUx)9*$NL3~GN_nh>oJ;mDW;mMl7NEKXh@-;UK6F(jX6bzVHg>eG>Usym8O8Dr5@QF zpa>GG0koi@SQ{| delta 234 zcmWNLF-inM5Jef>Xd*MyVNcLi)m7DHYQRK6VY9{DXkoxZcnvS&IgD)h(c|;q z|2ci1Zl53Kl{_+cpl$&Hykl3T)DY|U@+wSftGpQOy z^X_GSs;UxPa4_FFHlL@?OqbW2%KgIsa@A>;>$oL1`g^?WLo)~jU%u|5cF9Zrm^ogztU|L+5QFlKRbarH0!G=3e%@k77S{E+u^Q(~yw+=B~=Jz^2I6dWTF z_!O}vXKjkU^;XdJ?xZ%tjuC=uz9LmHr`_)&%XHffrJ?tb53cJsnAs6Gkq%UHg9g51 ziIF6>fF*<&190$#obqN}MIXFw#|l84JlO~YwYR{Md!m*h2lAF;q8eIGA!ACh5@L0k zRTT>~tGEh+^+v<2!}#rVG$LEntqJpedB4jR@%em_dEv`_Pj2MT{ro7+pe6gsg3hzG zPy2j%i1cbcjMVqa_j$T4pI_(O^&cJ0#PhWKJpNTTv0k?sSMUWKLS!w+TNXW+0@$1r zm53oXDvh-SCm`B^=)~facf}I}nB8$bJr@0x>&r5!Z;0tYzvXQ{?_ppA>u{+5e^`h0 MFVhk>B`N{{0R6^-WT4rl~JDQBiOvmtKI-%Y;cJjfbF@yK0f!1Xvw9 zysAy5Lw3v=Lhnums@1Ez76>L`KM)O5I zah2KT2GuL)98w(ac9v<3Xkd*~+eJh#XUU-8~NcdH4K+f5FS2PtVUUziasP{O#%64^0f@%m4rY delta 803 zcmWksP0AHP3|t6;u3Ues4^NPE()sZ=Nhb|%6cpUa!vhGey@nSw52j&eI!RTk>hH_1 zmp{KBWE%^ypC`m4cbU?;1-Pr#>)4huY6uW$rP{PhVON03S%Qu&d1iuSR<#rCLxytj zY_pwg=WaZVx9d1a?9PTJ3Q2n`Lf*xYMLp%MdS;p~PFa_8op1#huwjrPK&X(nNOlL- z+TD6x1dT0_?{*XuzW{d{D1uM2Sa7wlX5IxmU9Lx14eZ1EIT)|cUbmHHbKORAW}KJ7 z!6a5n(JTZm-Hf<;JBJ_X(P?Qrr^8lStAyYx9H#?VaOPR*b|tcItuBqDb@r^grr`0E zZz#L3t=x6PX=kojCnH2Rt)me&T(_;<6ywVoueNCE5Y8YwN10lu)ze3hHRAHT za~efj$kAMw-K`vAsj)uhcUx4Ctk;f3%y>bCBi<8bGhPz*__H##;OoDSWy;?nHnmkfYB8VfKzIaC0c#(NSRpiU#dF`PlbN#xGwqoLHPjCf0 diff --git a/tests/repository_data/repository/metadata.staged/role1.json b/tests/repository_data/repository/metadata.staged/role1.json index 96d921b5eb554f8230f22c434e84f563d2bde810..bfad965f1602eb39e47c03737de909ba03515aa8 100644 GIT binary patch delta 166 zcmV~$yA1*{3;<9aRM4^jx&e^m#GkMPBcOb2i3SiSkf`XX*yWaB4L0Gu@9MYuyk8}H z3&s~>mizbg1 tLWX9Fh(@GQS%{p-BtcOa`n(?Qi_LVkc6``vI$h4=emjO8%+KXv_yd9rE?)ou delta 146 zcmWN_u@%BF35dq zEN<*6>6nNnU4se+vkaaTg}|0d-hCE?0*l26tGg%?sFTFb;7UV_rk(<$SJ8Bh)|AyM U>ZpyX&7e(>+xEB|pX+`518V;$PXGV_ diff --git a/tests/repository_data/repository/metadata.staged/role1.json.gz b/tests/repository_data/repository/metadata.staged/role1.json.gz index e2fd36f00b5d950d4b88ee2ee8286bc891929560..a1ba3cc4f6ef413fd6eef22bc180cb823fc354b6 100644 GIT binary patch literal 630 zcmV-+0*U<}iwFQiN{iHwc8Nf5h5iz5F% z`I2Pa>jub%L=wE5bNIR0Hbb}D)A)Mgp?TQ;+-$d>_1iYT_@gV;(hxWcg0U2K+JMg4 zFlP*;vU7syusE%w(T1R!G=-qZgv6!9lqoiMbG{cI+rylY3tFo#_F8_fq9rSI-bcWa zGoWLK0j&w_IHLAqT~iM;sZo5Nvv`x3Q#MJxkv)>1 zKt#4S=-|AyVl8_E6rePzma&GYzi}j(O*YNwXTUM$;(C`gZJ&ynn^ZBueXgG3ye&f?nWi&;qdsrOfDz%HUzDw7$ zz8~Mmo4zJF@bHI9RuN2jjFPHrvDyb!R3>Zc##o>VR!-H$#$;3!V-P|L1eS<0W&jMq zr7I?@jwZo~O-w?{fl(=!Qc3r!?v8LOCR7c$T&xkV>&Dg_nF88oh~7pAp|EkDJZ0cy zgSWZ>8Y~jL&KfL-BvKdJSVNULF~$TCWm$-8`?u|E*KWZrm^oz56Q+pVO9-NLk8v=aQeM%e2+ia}~KwJXKfb-gCUv^g6 z){xK9Cq%D28*AJQh(iM3lx8kf{rs>oB6F)V6V1!?agw>kCqD0F8kfGCB!ldD>W_zU zOI#?s9sUDv*GiifFCCBF3lF>Fxu3fIRjnmq>{yds8QspLbh93xAMRzYSUzd6UcK>f zf3j{)uVLupoNIzoy3i^*1y;yfvIZ1FEnZN0(%yua4WPC}Vp1z8nK+9nQOjE!m+JPv ztkR#4gWO?!0{aQwKQs9k4+q{aB+T#Y8wDqxy5-qh-X!OJUuL5}%ofc&jB>l`%Di;P zVRnhS1ADGEaE-j5`gNol4F3zD}XjWauKg_Uc zT?#8yxkboiTBnkVOc)#!aN#6|awUjSEB4-H*6es53XVDgXy=+Xmis0Kac;J$tZMo$L63De=%Gjb#*|jDbAaNmQ zP8tch2$T`gK~^N0rL-RttWvH1sGC6!yQwREX;*C&uk60bc`T#1l7Fc#zX8(V<;ute F0093UC;tEd diff --git a/tests/repository_data/repository/metadata.staged/role2.json b/tests/repository_data/repository/metadata.staged/role2.json index 20b1206a703a64ca9c8c92070f4e43f3c894085c..e15e356b57e447c1006facc1a34aa19e40978903 100644 GIT binary patch delta 164 zcmV~$I|>3p3;Ed*VE$n`Fy=h$K8YnSl`3`55Fugm;e9( delta 144 zcmV~$yAc9037`!ZV8%aw~*dpvQ OMbnY*%kg}Fj_V(?D<~}h diff --git a/tests/repository_data/repository/metadata.staged/role2.json.gz b/tests/repository_data/repository/metadata.staged/role2.json.gz index 6074f9bdfd6b611f2ac527c62c1ab56896f80073..8e7b33d88d1fce7612ef18b02e4f193373bbe6e9 100644 GIT binary patch literal 312 zcmV-80muFyiwFQiN1V&#R~H{+Pm)kDaMICG&wbR1 z5HpF*z0NkWptITpB#kjiP7ot?V9@yl#T6V%!I8onx*Vl&XqUT8w&!3&$3gql5fF<- z({-K^vWuAjRDroS?RND@L}t`E3ALN97nu<^H0)&>E4N}f%ATgf`7}NTYh?9uUp5=g z$0gJ4tX+S}@8z%rtq=^nfG)KGSl4=6q{oZo-H!}o5uYdZD=ZJw1K??){)co^=+iwFSh1KU>u|22?HZo@DPME5?0p>+ySAIf6RkyVSJpiL?@njdVpXb|M? zmF)ze78*!zhI6lKGxmowPd|f>W?O$$b$u_VHs5;dr6`6WB4kG*8hrrYbwRariES5S zb}l-J-c#^_p-7%nvK&&YBGh(FX0z~4I(=Ohpo&AZFTL2$V#?BSvKTBjO36!#np+#m zHZ0T>zLm@ka%hC8c(k6p03l|JkT_?=Hbwy?m$PGWIe05ExhN4s03ar3TVz%QpM7o! zTObt-lz~kN^Qh|m=GlnOQRgPi=XAU39C63PL8o!aZA6cH;Hkfy$LGVPvgPtvHybX; zwbT8~UViD{wO@-i4m`YpEwcmIF7v*kr>D=0WPWuRi%}75RYE@g0ng)=5VipT09=xb A4FCWD diff --git a/tests/repository_data/repository/metadata.staged/root.json b/tests/repository_data/repository/metadata.staged/root.json index ab8e8dc8598b5d2196fd1ad728ce06d1bd51f58e..27ff6595124ca68bff53cc1e829ae57bb2de30f3 100644 GIT binary patch delta 828 zcmYLHOR5z(5FH4DZwZbbZ`RN>^-WT4rl~JDQBiOvmtKI-%Y;cJjfbF@yK0f!1Xvw9 zysAy5Lw3v=Lhnums@1Ez76>L`KM)O5I zah2KT2GuL)98w(ac9v<3Xkd*~+eJh#XUU-8~NcdH4K+f5FS2PtVUUziasP{O#%64^0f@%m4rY delta 803 zcmWlXJC0T{4226MB&evT8nFUDSChIwM!Rcx9F;jC9*E-DX3+qVUAIqPHkZ3 zR$VJih_t4~p}0{CZpaC0^N>f03SFNnd%2+sNQ0dKMbQKbWfHuHA>0WUn%Ox%7q7?e z!*<3n^{PUQmN-)b%bjvgGLS@ZOol)i})*>J>-T{0#u|-_@u0Vtf5hqLaFzxn+%sa-o*Z9%C zkX-DLTEQ~B1Lz!>XdZ8++Y>0UF4`Q4^ANGuU{=FP)GcWOp^2|z+ul$P!)=wRJO7LIPQS*GO{cHeaUy>1)9 bf3NTA!>3>O$Iq|dzkUAlj31w0KEC`1zUJKA diff --git a/tests/repository_data/repository/metadata.staged/snapshot.json b/tests/repository_data/repository/metadata.staged/snapshot.json index bf565452c904a703d13ee5b27936065ab8a508e4..2b55b31b57233a20c62e3a695647bc20105b0a95 100644 GIT binary patch delta 241 zcmWm6F-k;141i(w!8X=f*vUJ9CYi}hVr4DfK_-&~wo!4x*4|2ackmjX#(TKd|HuEm z|Ji?jyl2YnM8X0Do;6HkQfZ8!Oqm1JODp6Wq6SQOiUoUmhDVNU)rPb|BQq-?wx-z` zYba2P4hl_as!nEuYLieRE8b6>VQ1Uf?)NUDsu<#E(T8LyJ<@%8W=F&l$Q>d}s43WF r{r`gYFs`alW4l={7p~j=@^F59iTU^zugAml(|UWg;x(+>*K+X(hwVfi delta 233 zcmWO0J4!@B5QSmp!Xy)!nhkEiuCD5O7#WM3sOqi;69*K`26H3f?!j%i8uwvmC-~uf zzsH~B_t&Qpm;<&bonR)mG6d>0qC&z9V@$7IgL(i#Q8nS{qSiINH4o>UbBc~Woj3r* z3LsYnPbN!9svv+fJV>$%CHNeQ>fOr$_tW9;v7i$6j!}I9kWr1+_R7g1v>YVZ8mSB> m@mR@vuEmmV0eHXPZntXt)AoGxk#FxWm)E<8Gn~%X)Ab*_wm-!H diff --git a/tests/repository_data/repository/metadata.staged/snapshot.json.gz b/tests/repository_data/repository/metadata.staged/snapshot.json.gz index 88aa0f12c90f526ce4bca0793f7d405c7e8b082b..a767bfb9e84cbaa8b8d65ed951a91dde8e736b62 100644 GIT binary patch literal 396 zcmV;70dxKziwFQiN*65xh80Er z`(!)ausv)OC_p-$j>mi5b!IvqPI>-%k;&Y5A9h{$+ID9?%geDg#9$)AP*MWuJ=Chu zmb1lTJ2TXTzK`DJ;shF)J$uT@a3IjRMD)#m7GGRtf~$WLtu>_oiLCl&LpfUFjp!i zlM6|hsMs1C-9s_W%yrj&+}{$B#p;rTd759&vRHh7%I9eq=he88@8{!|nIW+74zSe& z!2Mc}8>tPQZ#td1jL(91pQiEj26g6}T&Cj+-~wFtKbiEO%yIsMIOJ(qeQozP&XCE6 zHF00aE q{%W;20ssKmAjFFR literal 387 zcmV-}0et=+iwFSh1KU>u|BX;xZ`&{oeD|*q^qdu1Cfs*MsT^9$jH?%17 z-%C5`fbC(MKmpY0a6H~?XY72~A9?w4mf7B$FP$;3dX4=iFNa!HD~8qaD6{G zJ%klO`{Mcxp`}1vNt}WlO7NVqR7_B%FLt--eV1jNHbLoq2=I>U_!TS!g#kl#jbISe zNeTQ=h#aLD*IDdauGA_JxSUIhwWVBI77l?cM;V48<-QF}u>z#x0He>q5~&CXc}Rdm zRi{aOA^{%yjF}rdv})$knTOpi5m~LSN!YK;%Sl#?ACG*R$7$J&TX{Ymu9;cy(0y>A z^~t&Wtv+8#x-{Q(j6F|J0(Xz|bbN=5{VC`9umP|Fm)$R>|4-(${6QRf9yedtx2`j? z4{FcY?h)wAY{5pyB!*++?xNMojiAy7_zq{LMz8mxCkV$pn~-4w5*jeU~iei>C4 h(U;xdTrPax%QF9CqwdE4{o~SI-T-FEttqAg006FZytM!T diff --git a/tests/repository_data/repository/metadata.staged/targets.json b/tests/repository_data/repository/metadata.staged/targets.json index 0620bfe42a0edd920cac821b7909ca1fb47c318d..920f63eba22c770c16606961d65eb0a570fae083 100644 GIT binary patch delta 166 zcmWN{yA8rX3;<9ibSNDQpbUU)=ROY0Alv7YXaEt3mYxD3)}Tzy8q7mp{l49=dp+&} z6_qOmuADMs6^I(J#-at)q}Dp98&wwyA|<;?(vg6c!xDU8&`8ckNUm{2K@BtrX_Tlj tn+uB;DFql72$le{1selGlje2vY&X-z?Qrw!bUdH>{kF#)%*(9(Se8ITbP#rnxW= z$(nNk03$R}vDpeSn-L9n89bC-2%}|XuV@}wW)l((7`)s&q4d$oES!2^w*^ayo0 TUBt9HF>HDr+jGA@xA*=BBY-KC diff --git a/tests/repository_data/repository/metadata.staged/targets.json.gz b/tests/repository_data/repository/metadata.staged/targets.json.gz index 0753ea6945da4785543f5d99659a1b8a641a608d..3b280cb261b5158ef942bdc008ba8bfce26579b6 100644 GIT binary patch literal 826 zcmV-A1I7FwiwFQiNlaNztOn zzprLIapGckFFTkqAc`jW9v}H@vmM6$cP-svZ zNY&P&w(2YgFBpBOOi7|@qy{L!EELpxm(ZsOp{PrFxLe{q*|a+@0j=Wfvf6w4*~l)t zEDc$jgea~l_{^^PnybsDXKs|OU^7Klti|Su385hdtbr&ou|hYIia2G-R%_~j(>2oCi-(<# zy9Yfy9?$z}_w?4S#bMkj`fy=%J$r}4<#>Ph9_9_pO%Ej`bNzk2wElcN*gK3Hus7)b zH0z|%)vgcH?s%Bx zwY?{*%$zGhGN87>#os=+tOEj7BO z#;fqk%QzjMKFDYGc{t5AkK-!XAq2jly7Xc@%<8i7!@pKd&AvWM39)%sQlctJu=j&O z)kh^4t9VWTnG{%(=fLF1SYo#`RJ~HX%5om}5Sc)OXj2nQEft8-nfe+fwmv6-o(s2l%k6)##2$+Yfp~x_)C=Rj&8k>{faDW8mlC#q6-|>-1oOdJ%U!Eo zr0E}60*{$H3C@6el#G(N4`E21`4l}tGmn*{%|q7(uc1#}sgASw7)gvmE-pGQ+_-N( z<50+gkZ19}?^0hN(+eBJw0uKc}_I_fOe`6_aR$X5t{Vvo_-|Ob}Z@nl_JXQt( E0PicI3IG5A literal 816 zcmV-01JC>)iwFSh1KU>u|D{yhZW}oaefL)w^PKKdBz5a|^l2ACKuJ_=)Q$tsq-as( z-^&?KoVeKCmj%WKL{a47;URx+w!^r8e3I$qtmE)``}bzM{b|4L@Kt~8n^^_{fey7p zYSMd@-kg@;6Gk5zQ%+GNQU^@HoG6I*E~C#8LKTa;s80kz@mvf3^EY>cd$ z?TxkwSuDO!L3_>>0K5YXF-XSloT6BoQbO`6`V!bR)UMPUmZn`KgE|2ZrI$kN0wrRR zR+yS2sZb+(G{~)Etn9fGdx(R9dEIR9?^Z^1hB`AbJWM~Hb%yvw&W}2c3+|!mK_6w> zpPt6maiQ#bn0X5xI_B0i5Chd}C00!0Y6u-MU<*W<4IP+?Bqb+SnYNZom3)n~_TphD z($N%X?Hrz z@^SAK-*48c2mSuMzs%ZzK=28ieO~}RFW+Ambxo_(-juaKaSN2IzUs?3osJ(=GW$F{ z&(Owk)#VTZU%+1|-wv~gbo}sYmCo$zOR6Du?`qD}Qch^JGl=*oG?j93oa^iY#V1t~44Rk6p$FNnCs7q=QlNXLM3pU2v+7J5lIPDA7P2v)qbKOV?~eFPi*PmSjwAKz8B?w)AOvWi?CleufG5x${dzG1^@sh9F+wC diff --git a/tests/repository_data/repository/metadata.staged/timestamp.json b/tests/repository_data/repository/metadata.staged/timestamp.json index 3f44ae9773a9bac7997713a8eb7bc3f9f1f1e362..1c425c1a0fc4eaf676a96da69387f8ef51d9390e 100644 GIT binary patch delta 259 zcmYL@J4ysW6h&#As5fBRbS8+rs`oc?CsOsQ3QSZSm~5EbNN8{oZo`eZ4kJ4=y&TTD zUx)9*$NL3~GN_nh>oJ;mDW;mMl7NEKXh@-;UK6F(jX6bzVHg>eG>Usym8O8Dr5@QF zpa>GG0koi@SQ{| delta 234 zcmWNLF-inM5Jef>Xd*MyVNcLi)m7DHYQRK6VY9{DXkoxZcnvS&IgD)h(c|;q z|2ci1Zl53Kl{_+cpl$&Hykl3T)DY|U@+wSftGpQOy z^X_GSs;UxPa4_FFHlL@?OqbW2%KgIsa@A>;>$oL1`g^?WLo)~jU%u|5cF9Zrm^ogztU|L+5QFlKRbarH0!G=3e%@k77S{E+u^Q(~yw+=B~=Jz^2I6dWTF z_!O}vXKjkU^;XdJ?xZ%tjuC=uz9LmHr`_)&%XHffrJ?tb53cJsnAs6Gkq%UHg9g51 ziIF6>fF*<&190$#obqN}MIXFw#|l84JlO~YwYR{Md!m*h2lAF;q8eIGA!ACh5@L0k zRTT>~tGEh+^+v<2!}#rVG$LEntqJpedB4jR@%em_dEv`_Pj2MT{ro7+pe6gsg3hzG zPy2j%i1cbcjMVqa_j$T4pI_(O^&cJ0#PhWKJpNTTv0k?sSMUWKLS!w+TNXW+0@$1r zm53oXDvh-SCm`B^=)~facf}I}nB8$bJr@0x>&r5!Z;0tYzvXQ{?_ppA>u{+5e^`h0 MFVhk>B`N{{0R6^-WT4rl~JDQBiOvmtKI-%Y;cJjfbF@yK0f!1Xvw9 zysAy5Lw3v=Lhnums@1Ez76>L`KM)O5I zah2KT2GuL)98w(ac9v<3Xkd*~+eJh#XUU-8~NcdH4K+f5FS2PtVUUziasP{O#%64^0f@%m4rY delta 803 zcmWksP0AHP3|t6;u3Ues4^NPE()sZ=Nhb|%6cpUa!vhGey@nSw52j&eI!RTk>hH_1 zmp{KBWE%^ypC`m4cbU?;1-Pr#>)4huY6uW$rP{PhVON03S%Qu&d1iuSR<#rCLxytj zY_pwg=WaZVx9d1a?9PTJ3Q2n`Lf*xYMLp%MdS;p~PFa_8op1#huwjrPK&X(nNOlL- z+TD6x1dT0_?{*XuzW{d{D1uM2Sa7wlX5IxmU9Lx14eZ1EIT)|cUbmHHbKORAW}KJ7 z!6a5n(JTZm-Hf<;JBJ_X(P?Qrr^8lStAyYx9H#?VaOPR*b|tcItuBqDb@r^grr`0E zZz#L3t=x6PX=kojCnH2Rt)me&T(_;<6ywVoueNCE5Y8YwN10lu)ze3hHRAHT za~efj$kAMw-K`vAsj)uhcUx4Ctk;f3%y>bCBi<8bGhPz*__H##;OoDSWy;?nHnmkfYB8VfKzIaC0c#(NSRpiU#dF`PlbN#xGwqoLHPjCf0 diff --git a/tests/repository_data/repository/metadata/role1.json b/tests/repository_data/repository/metadata/role1.json index 96d921b5eb554f8230f22c434e84f563d2bde810..bfad965f1602eb39e47c03737de909ba03515aa8 100644 GIT binary patch delta 166 zcmV~$yA1*{3;<9aRM4^jx&e^m#GkMPBcOb2i3SiSkf`XX*yWaB4L0Gu@9MYuyk8}H z3&s~>mizbg1 tLWX9Fh(@GQS%{p-BtcOa`n(?Qi_LVkc6``vI$h4=emjO8%+KXv_yd9rE?)ou delta 146 zcmWN_u@%BF35dq zEN<*6>6nNnU4se+vkaaTg}|0d-hCE?0*l26tGg%?sFTFb;7UV_rk(<$SJ8Bh)|AyM U>ZpyX&7e(>+xEB|pX+`518V;$PXGV_ diff --git a/tests/repository_data/repository/metadata/role1.json.gz b/tests/repository_data/repository/metadata/role1.json.gz index e2fd36f00b5d950d4b88ee2ee8286bc891929560..a1ba3cc4f6ef413fd6eef22bc180cb823fc354b6 100644 GIT binary patch literal 630 zcmV-+0*U<}iwFQiN{iHwc8Nf5h5iz5F% z`I2Pa>jub%L=wE5bNIR0Hbb}D)A)Mgp?TQ;+-$d>_1iYT_@gV;(hxWcg0U2K+JMg4 zFlP*;vU7syusE%w(T1R!G=-qZgv6!9lqoiMbG{cI+rylY3tFo#_F8_fq9rSI-bcWa zGoWLK0j&w_IHLAqT~iM;sZo5Nvv`x3Q#MJxkv)>1 zKt#4S=-|AyVl8_E6rePzma&GYzi}j(O*YNwXTUM$;(C`gZJ&ynn^ZBueXgG3ye&f?nWi&;qdsrOfDz%HUzDw7$ zz8~Mmo4zJF@bHI9RuN2jjFPHrvDyb!R3>Zc##o>VR!-H$#$;3!V-P|L1eS<0W&jMq zr7I?@jwZo~O-w?{fl(=!Qc3r!?v8LOCR7c$T&xkV>&Dg_nF88oh~7pAp|EkDJZ0cy zgSWZ>8Y~jL&KfL-BvKdJSVNULF~$TCWm$-8`?u|E*KWZrm^oz56Q+pVO9-NLk8v=aQeM%e2+ia}~KwJXKfb-gCUv^g6 z){xK9Cq%D28*AJQh(iM3lx8kf{rs>oB6F)V6V1!?agw>kCqD0F8kfGCB!ldD>W_zU zOI#?s9sUDv*GiifFCCBF3lF>Fxu3fIRjnmq>{yds8QspLbh93xAMRzYSUzd6UcK>f zf3j{)uVLupoNIzoy3i^*1y;yfvIZ1FEnZN0(%yua4WPC}Vp1z8nK+9nQOjE!m+JPv ztkR#4gWO?!0{aQwKQs9k4+q{aB+T#Y8wDqxy5-qh-X!OJUuL5}%ofc&jB>l`%Di;P zVRnhS1ADGEaE-j5`gNol4F3zD}XjWauKg_Uc zT?#8yxkboiTBnkVOc)#!aN#6|awUjSEB4-H*6es53XVDgXy=+Xmis0Kac;J$tZMo$L63De=%Gjb#*|jDbAaNmQ zP8tch2$T`gK~^N0rL-RttWvH1sGC6!yQwREX;*C&uk60bc`T#1l7Fc#zX8(V<;ute F0093UC;tEd diff --git a/tests/repository_data/repository/metadata/role2.json b/tests/repository_data/repository/metadata/role2.json index 20b1206a703a64ca9c8c92070f4e43f3c894085c..e15e356b57e447c1006facc1a34aa19e40978903 100644 GIT binary patch delta 164 zcmV~$I|>3p3;Ed*VE$n`Fy=h$K8YnSl`3`55Fugm;e9( delta 144 zcmV~$yAc9037`!ZV8%aw~*dpvQ OMbnY*%kg}Fj_V(?D<~}h diff --git a/tests/repository_data/repository/metadata/role2.json.gz b/tests/repository_data/repository/metadata/role2.json.gz index 6074f9bdfd6b611f2ac527c62c1ab56896f80073..8e7b33d88d1fce7612ef18b02e4f193373bbe6e9 100644 GIT binary patch literal 312 zcmV-80muFyiwFQiN1V&#R~H{+Pm)kDaMICG&wbR1 z5HpF*z0NkWptITpB#kjiP7ot?V9@yl#T6V%!I8onx*Vl&XqUT8w&!3&$3gql5fF<- z({-K^vWuAjRDroS?RND@L}t`E3ALN97nu<^H0)&>E4N}f%ATgf`7}NTYh?9uUp5=g z$0gJ4tX+S}@8z%rtq=^nfG)KGSl4=6q{oZo-H!}o5uYdZD=ZJw1K??){)co^=+iwFSh1KU>u|22?HZo@DPME5?0p>+ySAIf6RkyVSJpiL?@njdVpXb|M? zmF)ze78*!zhI6lKGxmowPd|f>W?O$$b$u_VHs5;dr6`6WB4kG*8hrrYbwRariES5S zb}l-J-c#^_p-7%nvK&&YBGh(FX0z~4I(=Ohpo&AZFTL2$V#?BSvKTBjO36!#np+#m zHZ0T>zLm@ka%hC8c(k6p03l|JkT_?=Hbwy?m$PGWIe05ExhN4s03ar3TVz%QpM7o! zTObt-lz~kN^Qh|m=GlnOQRgPi=XAU39C63PL8o!aZA6cH;Hkfy$LGVPvgPtvHybX; zwbT8~UViD{wO@-i4m`YpEwcmIF7v*kr>D=0WPWuRi%}75RYE@g0ng)=5VipT09=xb A4FCWD diff --git a/tests/repository_data/repository/metadata/root.json b/tests/repository_data/repository/metadata/root.json index ab8e8dc8598b5d2196fd1ad728ce06d1bd51f58e..27ff6595124ca68bff53cc1e829ae57bb2de30f3 100644 GIT binary patch delta 828 zcmYLHOR5z(5FH4DZwZbbZ`RN>^-WT4rl~JDQBiOvmtKI-%Y;cJjfbF@yK0f!1Xvw9 zysAy5Lw3v=Lhnums@1Ez76>L`KM)O5I zah2KT2GuL)98w(ac9v<3Xkd*~+eJh#XUU-8~NcdH4K+f5FS2PtVUUziasP{O#%64^0f@%m4rY delta 803 zcmWlXJC0T{4226MB&evT8nFUDSChIwM!Rcx9F;jC9*E-DX3+qVUAIqPHkZ3 zR$VJih_t4~p}0{CZpaC0^N>f03SFNnd%2+sNQ0dKMbQKbWfHuHA>0WUn%Ox%7q7?e z!*<3n^{PUQmN-)b%bjvgGLS@ZOol)i})*>J>-T{0#u|-_@u0Vtf5hqLaFzxn+%sa-o*Z9%C zkX-DLTEQ~B1Lz!>XdZ8++Y>0UF4`Q4^ANGuU{=FP)GcWOp^2|z+ul$P!)=wRJO7LIPQS*GO{cHeaUy>1)9 bf3NTA!>3>O$Iq|dzkUAlj31w0KEC`1zUJKA diff --git a/tests/repository_data/repository/metadata/snapshot.json b/tests/repository_data/repository/metadata/snapshot.json index bf565452c904a703d13ee5b27936065ab8a508e4..2b55b31b57233a20c62e3a695647bc20105b0a95 100644 GIT binary patch delta 241 zcmWm6F-k;141i(w!8X=f*vUJ9CYi}hVr4DfK_-&~wo!4x*4|2ackmjX#(TKd|HuEm z|Ji?jyl2YnM8X0Do;6HkQfZ8!Oqm1JODp6Wq6SQOiUoUmhDVNU)rPb|BQq-?wx-z` zYba2P4hl_as!nEuYLieRE8b6>VQ1Uf?)NUDsu<#E(T8LyJ<@%8W=F&l$Q>d}s43WF r{r`gYFs`alW4l={7p~j=@^F59iTU^zugAml(|UWg;x(+>*K+X(hwVfi delta 233 zcmWO0J4!@B5QSmp!Xy)!nhkEiuCD5O7#WM3sOqi;69*K`26H3f?!j%i8uwvmC-~uf zzsH~B_t&Qpm;<&bonR)mG6d>0qC&z9V@$7IgL(i#Q8nS{qSiINH4o>UbBc~Woj3r* z3LsYnPbN!9svv+fJV>$%CHNeQ>fOr$_tW9;v7i$6j!}I9kWr1+_R7g1v>YVZ8mSB> m@mR@vuEmmV0eHXPZntXt)AoGxk#FxWm)E<8Gn~%X)Ab*_wm-!H diff --git a/tests/repository_data/repository/metadata/snapshot.json.gz b/tests/repository_data/repository/metadata/snapshot.json.gz index 88aa0f12c90f526ce4bca0793f7d405c7e8b082b..a767bfb9e84cbaa8b8d65ed951a91dde8e736b62 100644 GIT binary patch literal 396 zcmV;70dxKziwFQiN*65xh80Er z`(!)ausv)OC_p-$j>mi5b!IvqPI>-%k;&Y5A9h{$+ID9?%geDg#9$)AP*MWuJ=Chu zmb1lTJ2TXTzK`DJ;shF)J$uT@a3IjRMD)#m7GGRtf~$WLtu>_oiLCl&LpfUFjp!i zlM6|hsMs1C-9s_W%yrj&+}{$B#p;rTd759&vRHh7%I9eq=he88@8{!|nIW+74zSe& z!2Mc}8>tPQZ#td1jL(91pQiEj26g6}T&Cj+-~wFtKbiEO%yIsMIOJ(qeQozP&XCE6 zHF00aE q{%W;20ssKmAjFFR literal 387 zcmV-}0et=+iwFSh1KU>u|BX;xZ`&{oeD|*q^qdu1Cfs*MsT^9$jH?%17 z-%C5`fbC(MKmpY0a6H~?XY72~A9?w4mf7B$FP$;3dX4=iFNa!HD~8qaD6{G zJ%klO`{Mcxp`}1vNt}WlO7NVqR7_B%FLt--eV1jNHbLoq2=I>U_!TS!g#kl#jbISe zNeTQ=h#aLD*IDdauGA_JxSUIhwWVBI77l?cM;V48<-QF}u>z#x0He>q5~&CXc}Rdm zRi{aOA^{%yjF}rdv})$knTOpi5m~LSN!YK;%Sl#?ACG*R$7$J&TX{Ymu9;cy(0y>A z^~t&Wtv+8#x-{Q(j6F|J0(Xz|bbN=5{VC`9umP|Fm)$R>|4-(${6QRf9yedtx2`j? z4{FcY?h)wAY{5pyB!*++?xNMojiAy7_zq{LMz8mxCkV$pn~-4w5*jeU~iei>C4 h(U;xdTrPax%QF9CqwdE4{o~SI-T-FEttqAg006FZytM!T diff --git a/tests/repository_data/repository/metadata/targets.json b/tests/repository_data/repository/metadata/targets.json index 0620bfe42a0edd920cac821b7909ca1fb47c318d..920f63eba22c770c16606961d65eb0a570fae083 100644 GIT binary patch delta 166 zcmWN{yA8rX3;<9ibSNDQpbUU)=ROY0Alv7YXaEt3mYxD3)}Tzy8q7mp{l49=dp+&} z6_qOmuADMs6^I(J#-at)q}Dp98&wwyA|<;?(vg6c!xDU8&`8ckNUm{2K@BtrX_Tlj tn+uB;DFql72$le{1selGlje2vY&X-z?Qrw!bUdH>{kF#)%*(9(Se8ITbP#rnxW= z$(nNk03$R}vDpeSn-L9n89bC-2%}|XuV@}wW)l((7`)s&q4d$oES!2^w*^ayo0 TUBt9HF>HDr+jGA@xA*=BBY-KC diff --git a/tests/repository_data/repository/metadata/targets.json.gz b/tests/repository_data/repository/metadata/targets.json.gz index 0753ea6945da4785543f5d99659a1b8a641a608d..3b280cb261b5158ef942bdc008ba8bfce26579b6 100644 GIT binary patch literal 826 zcmV-A1I7FwiwFQiNlaNztOn zzprLIapGckFFTkqAc`jW9v}H@vmM6$cP-svZ zNY&P&w(2YgFBpBOOi7|@qy{L!EELpxm(ZsOp{PrFxLe{q*|a+@0j=Wfvf6w4*~l)t zEDc$jgea~l_{^^PnybsDXKs|OU^7Klti|Su385hdtbr&ou|hYIia2G-R%_~j(>2oCi-(<# zy9Yfy9?$z}_w?4S#bMkj`fy=%J$r}4<#>Ph9_9_pO%Ej`bNzk2wElcN*gK3Hus7)b zH0z|%)vgcH?s%Bx zwY?{*%$zGhGN87>#os=+tOEj7BO z#;fqk%QzjMKFDYGc{t5AkK-!XAq2jly7Xc@%<8i7!@pKd&AvWM39)%sQlctJu=j&O z)kh^4t9VWTnG{%(=fLF1SYo#`RJ~HX%5om}5Sc)OXj2nQEft8-nfe+fwmv6-o(s2l%k6)##2$+Yfp~x_)C=Rj&8k>{faDW8mlC#q6-|>-1oOdJ%U!Eo zr0E}60*{$H3C@6el#G(N4`E21`4l}tGmn*{%|q7(uc1#}sgASw7)gvmE-pGQ+_-N( z<50+gkZ19}?^0hN(+eBJw0uKc}_I_fOe`6_aR$X5t{Vvo_-|Ob}Z@nl_JXQt( E0PicI3IG5A literal 816 zcmV-01JC>)iwFSh1KU>u|D{yhZW}oaefL)w^PKKdBz5a|^l2ACKuJ_=)Q$tsq-as( z-^&?KoVeKCmj%WKL{a47;URx+w!^r8e3I$qtmE)``}bzM{b|4L@Kt~8n^^_{fey7p zYSMd@-kg@;6Gk5zQ%+GNQU^@HoG6I*E~C#8LKTa;s80kz@mvf3^EY>cd$ z?TxkwSuDO!L3_>>0K5YXF-XSloT6BoQbO`6`V!bR)UMPUmZn`KgE|2ZrI$kN0wrRR zR+yS2sZb+(G{~)Etn9fGdx(R9dEIR9?^Z^1hB`AbJWM~Hb%yvw&W}2c3+|!mK_6w> zpPt6maiQ#bn0X5xI_B0i5Chd}C00!0Y6u-MU<*W<4IP+?Bqb+SnYNZom3)n~_TphD z($N%X?Hrz z@^SAK-*48c2mSuMzs%ZzK=28ieO~}RFW+Ambxo_(-juaKaSN2IzUs?3osJ(=GW$F{ z&(Owk)#VTZU%+1|-wv~gbo}sYmCo$zOR6Du?`qD}Qch^JGl=*oG?j93oa^iY#V1t~44Rk6p$FNnCs7q=QlNXLM3pU2v+7J5lIPDA7P2v)qbKOV?~eFPi*PmSjwAKz8B?w)AOvWi?CleufG5x${dzG1^@sh9F+wC diff --git a/tests/repository_data/repository/metadata/timestamp.json b/tests/repository_data/repository/metadata/timestamp.json index 3f44ae9773a9bac7997713a8eb7bc3f9f1f1e362..1c425c1a0fc4eaf676a96da69387f8ef51d9390e 100644 GIT binary patch delta 259 zcmYL@J4ysW6h&#As5fBRbS8+rs`oc?CsOsQ3QSZSm~5EbNN8{oZo`eZ4kJ4=y&TTD zUx)9*$NL3~GN_nh>oJ;mDW;mMl7NEKXh@-;UK6F(jX6bzVHg>eG>Usym8O8Dr5@QF zpa>GG0koi@SQ{| delta 234 zcmWNLF-inM5Jef>Xd*MyVNcLi)m7DHYQRK6VY9{DXkoxZcnvS&IgD)h(c|;q z|2ci1Zl53Kl{_+cpl$&Hykl3T)DY|U@+wSftGpQOy z^X_GSs;UxPa4_FFHlL@?OqbW2%KgIsa@A>;>$oL1`g^?WLo)~jU%u|5cF9Zrm^ogztU|L+5QFlKRbarH0!G=3e%@k77S{E+u^Q(~yw+=B~=Jz^2I6dWTF z_!O}vXKjkU^;XdJ?xZ%tjuC=uz9LmHr`_)&%XHffrJ?tb53cJsnAs6Gkq%UHg9g51 ziIF6>fF*<&190$#obqN}MIXFw#|l84JlO~YwYR{Md!m*h2lAF;q8eIGA!ACh5@L0k zRTT>~tGEh+^+v<2!}#rVG$LEntqJpedB4jR@%em_dEv`_Pj2MT{ro7+pe6gsg3hzG zPy2j%i1cbcjMVqa_j$T4pI_(O^&cJ0#PhWKJpNTTv0k?sSMUWKLS!w+TNXW+0@$1r zm53oXDvh-SCm`B^=)~facf}I}nB8$bJr@0x>&r5!Z;0tYzvXQ{?_ppA>u{+5e^`h0 MFVhk>B`N{{0R6 Date: Fri, 25 Aug 2017 12:52:11 -0400 Subject: [PATCH 04/24] Remove schemeta related to compression and update unit tests --- tests/test_formats.py | 34 ++++++++++------------------------ tuf/formats.py | 25 +++---------------------- 2 files changed, 13 insertions(+), 46 deletions(-) diff --git a/tests/test_formats.py b/tests/test_formats.py index 56e124e6..132051c1 100755 --- a/tests/test_formats.py +++ b/tests/test_formats.py @@ -358,11 +358,9 @@ def test_RootFile(self): ROOT_SCHEMA = tuf.formats.ROOT_SCHEMA self.assertTrue(ROOT_SCHEMA.matches(make_metadata(version, expires, - keydict, roledict, - consistent_snapshot, - compression_algorithms))) + keydict, roledict, consistent_snapshot))) metadata = make_metadata(version, expires, keydict, roledict, - consistent_snapshot, compression_algorithms) + consistent_snapshot) self.assertTrue(isinstance(from_metadata(metadata), tuf.formats.RootFile)) # Test conditions for invalid arguments. @@ -372,26 +370,14 @@ def test_RootFile(self): bad_roledict = 123 bad_compression_algorithms = ['nozip'] - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, bad_version, - expires, - keydict, roledict, - consistent_snapshot, - compression_algorithms) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, - bad_expires, - keydict, roledict, - consistent_snapshot, - compression_algorithms) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, - expires, - bad_keydict, roledict, - consistent_snapshot, - compression_algorithms) - self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, version, - expires, - keydict, bad_roledict, - consistent_snapshot, - compression_algorithms) + self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, + bad_version, expires, keydict, roledict, consistent_snapshot) + self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, + version, bad_expires, keydict, roledict, consistent_snapshot) + self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, + version, expires, bad_keydict, roledict, consistent_snapshot) + self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, + version, expires, keydict, bad_roledict, consistent_snapshot) self.assertRaises(securesystemslib.exceptions.FormatError, from_metadata, 'bad') diff --git a/tuf/formats.py b/tuf/formats.py index d0a055ed..b29a4d5a 100755 --- a/tuf/formats.py +++ b/tuf/formats.py @@ -147,10 +147,6 @@ # A value that is either True or False, on or off, etc. BOOLEAN_SCHEMA = SCHEMA.Boolean() -# List of supported compression extensions. -COMPRESSIONS_SCHEMA = SCHEMA.ListOf( - SCHEMA.OneOf([SCHEMA.String(''), SCHEMA.String('gz')])) - # A string representing a role's name. ROLENAME_SCHEMA = SCHEMA.AnyString() @@ -268,13 +264,6 @@ # as requiring them to be a power of 2. NUMBINS_SCHEMA = SCHEMA.Integer(lo=1) -# Supported compression extension (e.g., 'gz'). -COMPRESSION_SCHEMA = SCHEMA.OneOf([SCHEMA.String(''), SCHEMA.String('gz')]) - -# List of supported compression extensions. -COMPRESSIONS_SCHEMA = SCHEMA.ListOf( - SCHEMA.OneOf([SCHEMA.String(''), SCHEMA.String('gz')])) - # The fileinfo format of targets specified in the repository and # developer tools. The second element of this list holds custom data about the # target, such as file permissions, author(s), last modified, etc. @@ -295,7 +284,6 @@ version = SCHEMA.Optional(METADATAVERSION_SCHEMA), expires = SCHEMA.Optional(ISO8601_DATETIME_SCHEMA), signatures = SCHEMA.Optional(securesystemslib.formats.SIGNATURES_SCHEMA), - compressions = SCHEMA.Optional(COMPRESSIONS_SCHEMA), paths = SCHEMA.Optional(SCHEMA.OneOf([RELPATHS_SCHEMA, PATH_FILEINFO_SCHEMA])), path_hash_prefixes = SCHEMA.Optional(PATH_HASH_PREFIXES_SCHEMA), delegations = SCHEMA.Optional(DELEGATIONS_SCHEMA), @@ -313,7 +301,6 @@ _type = SCHEMA.String('root'), version = METADATAVERSION_SCHEMA, consistent_snapshot = BOOLEAN_SCHEMA, - compression_algorithms = COMPRESSIONS_SCHEMA, expires = ISO8601_DATETIME_SCHEMA, keys = KEYDICT_SCHEMA, roles = ROLEDICT_SCHEMA) @@ -532,16 +519,13 @@ def make_metadata(version, expiration_date, filedict): class RootFile(MetaFile): - def __init__(self, version, expires, keys, roles, consistent_snapshot, - compression_algorithms): + def __init__(self, version, expires, keys, roles, consistent_snapshot): self.info = {} self.info['version'] = version self.info['expires'] = expires self.info['keys'] = keys self.info['roles'] = roles self.info['consistent_snapshot'] = consistent_snapshot - self.info['compression_algorithms'] = compression_algorithms - @staticmethod def from_metadata(object): @@ -554,22 +538,19 @@ def from_metadata(object): keys = object['keys'] roles = object['roles'] consistent_snapshot = object['consistent_snapshot'] - compression_algorithms = object['compression_algorithms'] - return RootFile(version, expires, keys, roles, consistent_snapshot, - compression_algorithms) + return RootFile(version, expires, keys, roles, consistent_snapshot) @staticmethod def make_metadata(version, expiration_date, keydict, roledict, - consistent_snapshot, compression_algorithms): + consistent_snapshot): result = {'_type' : 'root'} result['version'] = version result['expires'] = expiration_date result['keys'] = keydict result['roles'] = roledict result['consistent_snapshot'] = consistent_snapshot - result['compression_algorithms'] = compression_algorithms # Is 'result' a Root metadata file? # Raise 'securesystemslib.exceptions.FormatError' if not. From 3bfa9f68edea2c4b86e29378d3ffccb56d7d13e9 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 13:27:03 -0400 Subject: [PATCH 05/24] Remove compression code from exceptions and update unit tests --- tests/test_exceptions.py | 6 ------ tuf/exceptions.py | 12 ------------ 2 files changed, 18 deletions(-) diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index b29b72b8..232071af 100755 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -51,12 +51,6 @@ def test_bad_hash_error(self): logger.error(bad_hash_error) - def test_decompression_error(self): - download_exception = tuf.exceptions.DownloadError() - decompression_error = tuf.exceptions.DecompressionError(download_exception) - logger.error(decompression_error) - - # Run the unit tests. if __name__ == '__main__': unittest.main() diff --git a/tuf/exceptions.py b/tuf/exceptions.py index a964d3b8..80e2bb05 100755 --- a/tuf/exceptions.py +++ b/tuf/exceptions.py @@ -149,18 +149,6 @@ class UnsupportedLibraryError(Error): pass -class DecompressionError(Error): - """Indicate that some error happened while decompressing a file.""" - - def __init__(self, exception): - # Store the original exception. - self.exception = exception - - def __str__(self): - # Show the original exception. - return repr(self.exception) - - class DownloadError(Error): """Indicate an error occurred while attempting to download a file.""" pass From 9fe00756efcaff2964270d3e628687270e07ebe1 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 13:46:31 -0400 Subject: [PATCH 06/24] Remove compression from roledb and update its unit tests --- tests/test_roledb.py | 12 +++--------- tuf/roledb.py | 1 - 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/tests/test_roledb.py b/tests/test_roledb.py index 88c5c613..eef9dea9 100755 --- a/tests/test_roledb.py +++ b/tests/test_roledb.py @@ -545,10 +545,7 @@ def test_create_roledb_from_root_metadata(self): compression_algorithms = ['gz'] root_metadata = tuf.formats.RootFile.make_metadata(version, - expires, - keydict, roledict, - consistent_snapshot, - compression_algorithms) + expires, keydict, roledict, consistent_snapshot) self.assertEqual(None, tuf.roledb.create_roledb_from_root_metadata(root_metadata)) @@ -594,12 +591,9 @@ def test_create_roledb_from_root_metadata(self): # Generate 'root_metadata' to verify that 'release' and 'root' are added # to the role database. root_metadata = tuf.formats.RootFile.make_metadata(version, - expires, - keydict, roledict, - consistent_snapshot, - compression_algorithms) + expires, keydict, roledict, consistent_snapshot) self.assertEqual(None, - tuf.roledb.create_roledb_from_root_metadata(root_metadata)) + tuf.roledb.create_roledb_from_root_metadata(root_metadata)) # Ensure only 'root' and 'release' were added to the role database. self.assertEqual(2, len(tuf.roledb._roledb_dict['default'])) diff --git a/tuf/roledb.py b/tuf/roledb.py index 26403569..9f098cbd 100755 --- a/tuf/roledb.py +++ b/tuf/roledb.py @@ -134,7 +134,6 @@ def create_roledb_from_root_metadata(root_metadata, repository_name='default'): roleinfo['signatures'] = [] roleinfo['signing_keyids'] = [] - roleinfo['compressions'] = [''] roleinfo['partial_loaded'] = False if rolename.startswith('targets'): From 60cd55229f6b73b4d3d8715e5c74b41fd87bb830 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 15:38:40 -0400 Subject: [PATCH 07/24] Remove compression logic from repository_lib.py and edit its unit tests --- tests/test_repository_lib.py | 98 +++++-------------- tuf/repository_lib.py | 176 ++++------------------------------- 2 files changed, 41 insertions(+), 233 deletions(-) diff --git a/tests/test_repository_lib.py b/tests/test_repository_lib.py index 675cce3e..79482e80 100755 --- a/tests/test_repository_lib.py +++ b/tests/test_repository_lib.py @@ -749,19 +749,17 @@ def test_write_metadata_file(self): root_signable = securesystemslib.util.load_json_file(root_filename) output_filename = os.path.join(temporary_directory, 'root.json') - compression_algorithms = ['gz'] version_number = root_signable['signed']['version'] + 1 self.assertFalse(os.path.exists(output_filename)) repo_lib.write_metadata_file(root_signable, output_filename, version_number, - compression_algorithms, consistent_snapshot=False) + consistent_snapshot=False) self.assertTrue(os.path.exists(output_filename)) - self.assertTrue(os.path.exists(output_filename + '.gz')) # Attempt to over-write the previously written metadata file. An exception # is not raised in this case, only a debug message is logged. repo_lib.write_metadata_file(root_signable, output_filename, version_number, - compression_algorithms, consistent_snapshot=False) + consistent_snapshot=False) # Try to write a consistent metadate file. An exception is not raised in # this case. For testing purposes, root.json should be a hard link to the @@ -769,7 +767,7 @@ def test_write_metadata_file(self): # the latest consistent files. tuf.settings.CONSISTENT_METHOD = 'hard_link' repo_lib.write_metadata_file(root_signable, output_filename, version_number, - compression_algorithms, consistent_snapshot=True) + consistent_snapshot=True) # Test if the consistent files are properly named # Filename format of a consistent file: .rolename.json @@ -780,9 +778,7 @@ def test_write_metadata_file(self): # Try to add more consistent metadata files. version_number += 1 repo_lib.write_metadata_file(root_signable, output_filename, - version_number, - compression_algorithms, - consistent_snapshot=True) + version_number, consistent_snapshot=True) # Test if the the latest root.json points to the expected consistent file # and consistent metadata do not all point to the same root.json @@ -796,76 +792,34 @@ def test_write_metadata_file(self): tuf.settings.CONSISTENT_METHOD = 'somebadidea' self.assertRaises(securesystemslib.exceptions.InvalidConfigurationError, repo_lib.write_metadata_file, root_signable, output_filename, - version_number, compression_algorithms, consistent_snapshot=True) + version_number, consistent_snapshot=True) # Try to create a link to root.json when root.json doesn't exist locally. # repository_lib should log a message if this is the case. tuf.settings.CONSISTENT_METHOD = 'hard_link' os.remove(output_filename) repo_lib.write_metadata_file(root_signable, output_filename, version_number, - compression_algorithms, consistent_snapshot=True) + consistent_snapshot=True) # Reset CONSISTENT_METHOD so that subsequent tests work as expected. tuf.settings.CONSISTENT_METHOD = 'copy' - # Test for unknown compression algorithm. - self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.write_metadata_file, - root_signable, output_filename, version_number, compression_algorithms=['bad_algo'], - consistent_snapshot=False) - # Test improperly formatted arguments. self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.write_metadata_file, - 3, output_filename, version_number, - compression_algorithms, False) + 3, output_filename, version_number, False) self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.write_metadata_file, - root_signable, 3, version_number, compression_algorithms, - False) + root_signable, 3, version_number, False) self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.write_metadata_file, - root_signable, output_filename, '3', - compression_algorithms, False) + root_signable, output_filename, '3', False) self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.write_metadata_file, - root_signable, output_filename, version_number, - compression_algorithms, 3) + root_signable, output_filename, version_number, 3) - def test__write_compressed_metadata(self): - # Test for invalid 'compressed_filename' argument and set - # 'write_new_metadata' to False. - file_object = securesystemslib.util.TempFile() - existing_filename = os.path.join('repository_data', 'repository', - 'metadata', 'root.json') - - write_new_metadata = False - repo_lib._write_compressed_metadata(file_object, - compressed_filename=existing_filename, - write_new_metadata=write_new_metadata, - consistent_snapshot=False, - version_number=8) - - # Test writing of compressed metadata when consistent snapshots is enabled. - file_object = securesystemslib.util.TempFile() - shutil.copy(existing_filename, os.path.join(self.temporary_directory, '8.root.json.gz')) - shutil.copy(existing_filename, os.path.join(self.temporary_directory, '8.root.json.zip')) - shutil.copy(existing_filename, os.path.join(self.temporary_directory, 'root.json.zip')) - compressed_filename = os.path.join(self.temporary_directory, 'root.json.gz') - - # For testing purposes, add additional compression algorithms to - # repo_lib.SUPPORTED_COMPRESSION_EXTENSIONS. - repo_lib.SUPPORTED_COMPRESSION_EXTENSIONS = ['gz', 'zip', 'bz2'] - repo_lib._write_compressed_metadata(file_object, - compressed_filename=compressed_filename, - write_new_metadata=True, - consistent_snapshot=True, - version_number=8) - repo_lib.SUPPORTED_COMPRESSION_EXTENSIONS = ['gz'] - - def test_create_tuf_client_directory(self): # Test normal case. temporary_directory = tempfile.mkdtemp(dir=self.temporary_directory) - repository_directory = os.path.join('repository_data', - 'repository') + repository_directory = os.path.join('repository_data', 'repository') client_directory = os.path.join(temporary_directory, 'client') repo_lib.create_tuf_client_directory(repository_directory, client_directory) @@ -881,15 +835,16 @@ def test_create_tuf_client_directory(self): # Test improperly formatted arguments. - self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.create_tuf_client_directory, - 3, client_directory) - self.assertRaises(securesystemslib.exceptions.FormatError, repo_lib.create_tuf_client_directory, - repository_directory, 3) + self.assertRaises(securesystemslib.exceptions.FormatError, + repo_lib.create_tuf_client_directory, 3, client_directory) + self.assertRaises(securesystemslib.exceptions.FormatError, + repo_lib.create_tuf_client_directory, repository_directory, 3) # Test invalid argument (i.e., client directory already exists.) - self.assertRaises(securesystemslib.exceptions.RepositoryError, repo_lib.create_tuf_client_directory, - repository_directory, client_directory) + self.assertRaises(securesystemslib.exceptions.RepositoryError, + repo_lib.create_tuf_client_directory, repository_directory, + client_directory) # Test invalid client metadata directory (i.e., non-errno.EEXIST exceptions # should be re-raised.) @@ -903,7 +858,7 @@ def test_create_tuf_client_directory(self): os.chmod(client_directory, current_client_directory_mode & ~stat.S_IWUSR) self.assertRaises(OSError, repo_lib.create_tuf_client_directory, - repository_directory, client_directory) + repository_directory, client_directory) # Reset the client directory's mode. os.chmod(client_directory, current_client_directory_mode) @@ -912,7 +867,8 @@ def test_create_tuf_client_directory(self): def test__check_directory(self): # Test for non-existent directory. - self.assertRaises(securesystemslib.exceptions.Error, repo_lib._check_directory, 'non-existent') + self.assertRaises(securesystemslib.exceptions.Error, + repo_lib._check_directory, 'non-existent') @@ -954,8 +910,7 @@ def test__generate_and_write_metadata(self): repo_lib._generate_and_write_metadata('obsolete_role', obsolete_metadata, targets_directory, metadata_directory, consistent_snapshot=False, - filenames=None, compression_algorithms=['gz'], - repository_name=repository_name) + filenames=None, repository_name=repository_name) snapshot_filepath = os.path.join('repository_data', 'repository', 'metadata', 'snapshot.json') @@ -1022,20 +977,13 @@ def test__load_top_level_metadata(self): signable = securesystemslib.util.load_json_file(os.path.join(metadata_directory, 'root.json')) signable['signatures'].append(signable['signatures'][0]) - repo_lib.write_metadata_file(signable, root_file, 8, ['gz'], False) + repo_lib.write_metadata_file(signable, root_file, 8, False) # Attempt to load a repository that contains a compressed Root file. repository = repo_tool.create_new_repository(repository_directory, repository_name) filenames = repo_lib.get_metadata_filenames(metadata_directory) repo_lib._load_top_level_metadata(repository, filenames, repository_name) - # Remove compressed metadata so that we can test for loading of a - # repository with no compression enabled. - for role_file in os.listdir(metadata_directory): - if role_file.endswith('.json.gz'): - role_filename = os.path.join(metadata_directory, role_file) - os.remove(role_filename) - filenames = repo_lib.get_metadata_filenames(metadata_directory) repository = repo_tool.create_new_repository(repository_directory, repository_name) repo_lib._load_top_level_metadata(repository, filenames, repository_name) diff --git a/tuf/repository_lib.py b/tuf/repository_lib.py index c189dbf5..703535de 100755 --- a/tuf/repository_lib.py +++ b/tuf/repository_lib.py @@ -96,9 +96,6 @@ # Supported key types. SUPPORTED_KEY_TYPES = ['rsa', 'ed25519'] -# The recognized compression extensions. -SUPPORTED_COMPRESSION_EXTENSIONS = ['.gz'] - # The full list of supported TUF metadata extensions. METADATA_EXTENSIONS = ['.json.gz', '.json'] @@ -107,12 +104,9 @@ def _generate_and_write_metadata(rolename, metadata_filename, - targets_directory, metadata_directory, - consistent_snapshot=False, filenames=None, - compression_algorithms=['gz'], - allow_partially_signed=False, - increment_version_number=True, - repository_name='default'): + targets_directory, metadata_directory, consistent_snapshot=False, + filenames=None, allow_partially_signed=False, increment_version_number=True, + repository_name='default'): """ Non-public function that can generate and write the metadata for the specified 'rolename'. It also increments the version number of 'rolename' if @@ -131,7 +125,7 @@ def _generate_and_write_metadata(rolename, metadata_filename, # Generate the appropriate role metadata for 'rolename'. if rolename == 'root': metadata = generate_root_metadata(roleinfo['version'], roleinfo['expires'], - consistent_snapshot, compression_algorithms, repository_name) + consistent_snapshot, repository_name) _log_warning_if_expires_soon(ROOT_FILENAME, roleinfo['expires'], ROOT_EXPIRES_WARN_SECONDS) @@ -221,7 +215,7 @@ def should_write(): if rolename == 'root': consistent_snapshot = True filename = write_metadata_file(signable, metadata_filename, - metadata['version'], compression_algorithms, consistent_snapshot) + metadata['version'], consistent_snapshot) # 'signable' contains an invalid threshold of signatures. else: @@ -247,13 +241,11 @@ def should_write(): # .root.json and root.json). if rolename == 'root': filename = write_metadata_file(signable, metadata_filename, - metadata['version'], compression_algorithms, - consistent_snapshot=True) + metadata['version'], consistent_snapshot=True) else: filename = write_metadata_file(signable, metadata_filename, - metadata['version'], compression_algorithms, - consistent_snapshot) + metadata['version'], consistent_snapshot) return signable, filename @@ -580,9 +572,6 @@ def _load_top_level_metadata(repository, top_level_filenames, repository_name): logger.debug('Found a Root signature that is already loaded:' ' ' + repr(signature)) - if os.path.exists(root_filename + '.gz'): - roleinfo['compressions'].append('gz') - else: logger.debug('A compressed Root file was not found.') @@ -620,11 +609,6 @@ def _load_top_level_metadata(repository, top_level_filenames, repository_name): roleinfo = tuf.roledb.get_roleinfo('timestamp', repository_name) roleinfo['expires'] = timestamp_metadata['expires'] roleinfo['version'] = timestamp_metadata['version'] - if os.path.exists(timestamp_filename + '.gz'): - roleinfo['compressions'].append('gz') - - else: - logger.debug('A compressed Timestamp file was not found.') if _metadata_is_partially_loaded('timestamp', signable, roleinfo, repository_name): roleinfo['partial_loaded'] = True @@ -665,11 +649,6 @@ def _load_top_level_metadata(repository, top_level_filenames, repository_name): roleinfo = tuf.roledb.get_roleinfo('snapshot', repository_name) roleinfo['expires'] = snapshot_metadata['expires'] roleinfo['version'] = snapshot_metadata['version'] - if os.path.exists(snapshot_filename + '.gz'): - roleinfo['compressions'].append('gz') - - else: - logger.debug('A compressed Snapshot file was not loaded.') if _metadata_is_partially_loaded('snapshot', signable, roleinfo, repository_name): roleinfo['partial_loaded'] = True @@ -708,11 +687,6 @@ def _load_top_level_metadata(repository, top_level_filenames, repository_name): roleinfo['version'] = targets_metadata['version'] roleinfo['expires'] = targets_metadata['expires'] roleinfo['delegations'] = targets_metadata['delegations'] - if os.path.exists(targets_filename + '.gz'): - roleinfo['compressions'].append('gz') - - else: - logger.debug('Compressed Targets file cannot be loaded.') if _metadata_is_partially_loaded('targets', signable, roleinfo, repository_name): roleinfo['partial_loaded'] = True @@ -1226,7 +1200,7 @@ def get_target_hash(target_filepath): def generate_root_metadata(version, expiration_date, consistent_snapshot, - compression_algorithms=['gz'], repository_name='default'): + repository_name='default'): """ Create the root metadata. 'tuf.roledb.py' and 'tuf.keydb.py' @@ -1248,11 +1222,6 @@ def generate_root_metadata(version, expiration_date, consistent_snapshot, filename of any target file located in the targets directory. Each digest is stripped from the target filename and listed in the snapshot metadata. - compression_algorithms: - A list of compression algorithms to use when generating the compressed - metadata files for the repository. The root file specifies the - algorithms used by the repository. - repository_name: The name of the repository. If not supplied, 'rolename' is added to the 'default' repository. @@ -1280,7 +1249,6 @@ def generate_root_metadata(version, expiration_date, consistent_snapshot, tuf.formats.METADATAVERSION_SCHEMA.check_match(version) securesystemslib.formats.ISO8601_DATETIME_SCHEMA.check_match(expiration_date) securesystemslib.formats.BOOLEAN_SCHEMA.check_match(consistent_snapshot) - tuf.formats.COMPRESSIONS_SCHEMA.check_match(compression_algorithms) securesystemslib.formats.NAME_SCHEMA.check_match(repository_name) # The role and key dictionaries to be saved in the root metadata object. @@ -1343,9 +1311,7 @@ def generate_root_metadata(version, expiration_date, consistent_snapshot, # Generate the root metadata object. root_metadata = tuf.formats.RootFile.make_metadata(version, expiration_date, - keydict, roledict, - consistent_snapshot, - compression_algorithms) + keydict, roledict, consistent_snapshot) return root_metadata @@ -1754,16 +1720,10 @@ def sign_metadata(metadata_object, keyids, filename, repository_name): -def write_metadata_file(metadata, filename, version_number, - compression_algorithms, consistent_snapshot): +def write_metadata_file(metadata, filename, version_number, consistent_snapshot): """ - If necessary, write the 'metadata' signable object to 'filename', and the - compressed version of the metadata file if 'compression' is set. - - Note: Compression algorithms like gzip attach a timestamp to compressed - files, so a metadata file compressed multiple times may generate different - digests even though the uncompressed content has not changed. + If necessary, write the 'metadata' signable object to 'filename'. metadata: @@ -1772,27 +1732,22 @@ def write_metadata_file(metadata, filename, version_number, filename: The filename of the metadata to be written (e.g., 'root.json'). - If a compression algorithm is specified in 'compression_algorithms', the - compression extention is appended to 'filename'. version_number: The version number of the metadata file to be written. The version number is needed for consistent snapshots, which prepend the version number to 'filename'. - compression_algorithms: - Specify the algorithms, as a list of strings, used to compress the - 'metadata'; The only currently available compression option is 'gz' - (gzip). - consistent_snapshot: Boolean that determines whether the metadata file's digest should be prepended to the filename. - securesystemslib.exceptions.FormatError, if the arguments are improperly formatted. + securesystemslib.exceptions.FormatError, if the arguments are improperly + formatted. - securesystemslib.exceptions.Error, if the directory of 'filename' does not exist. + securesystemslib.exceptions.Error, if the directory of 'filename' does not + exist. Any other runtime (e.g., IO) exception. @@ -1811,7 +1766,6 @@ def write_metadata_file(metadata, filename, version_number, tuf.formats.SIGNABLE_SCHEMA.check_match(metadata) securesystemslib.formats.PATH_SCHEMA.check_match(filename) tuf.formats.METADATAVERSION_SCHEMA.check_match(version_number) - tuf.formats.COMPRESSIONS_SCHEMA.check_match(compression_algorithms) securesystemslib.formats.BOOLEAN_SCHEMA.check_match(consistent_snapshot) # Verify the directory of 'filename', and convert 'filename' to its absolute @@ -1878,115 +1832,21 @@ def write_metadata_file(metadata, filename, version_number, os.link(written_consistent_filename, written_filename) else: - raise securesystemslib.exceptions.InvalidConfigurationError('The consistent method specified' - ' in tuf.settings.py is not supported, try either "copy" or "hard_link"') + raise securesystemslib.exceptions.InvalidConfigurationError('The' + ' consistent method specified in tuf.settings.py is not supported, try' + ' either "copy" or "hard_link"') else: logger.debug('Not creating a consistent snapshot for ' + repr(written_filename)) logger.debug('Saving ' + repr(written_filename)) file_object.move(written_filename) - # Generate the compressed versions of 'metadata', if necessary. A compressed - # file may be written (without needing to write the uncompressed version) if - # the repository maintainer adds compression after writing the uncompressed - # version. - for compression_algorithm in compression_algorithms: - file_object = None - - # Ignore the empty string that signifies non-compression. The uncompressed - # file was previously written above, if necessary. - if not len(compression_algorithm): - continue - - elif compression_algorithm == 'gz': - file_object = securesystemslib.util.TempFile() - compressed_filename = filename + '.gz' - - # Instantiate a gzip object, but save compressed content to - # 'file_object' (i.e., GzipFile instance is based on its 'fileobj' - # argument). - gzip_object = gzip.GzipFile(fileobj=file_object, mode='wb') - try: - gzip_object.write(file_content) - - finally: - gzip_object.close() - - # This else clause should not be reached because the - # 'compression_algorithms' list is validated against the - # COMPRESSIONS_SCHEMA above. - else: # pragma: no cover - raise securesystemslib.exceptions.FormatError('Unknown compression algorithm:' - ' ' + repr(compression_algorithm)) - - # Save the compressed version, ensuring an unchanged file is not re-saved. - # Re-saving the same compressed version may cause its digest to - # unexpectedly change (gzip includes a timestamp) even though content has - # not changed. - _write_compressed_metadata(file_object, compressed_filename, - True, consistent_snapshot, - version_number) return written_filename -def _write_compressed_metadata(file_object, compressed_filename, - write_new_metadata, consistent_snapshot, version_number): - """ - Write compressed versions of metadata, ensuring compressed file that have - not changed are not re-written, the digest of the compressed file is properly - added to the compressed filename, and consistent snapshots are also saved. - Ensure compressed files are written to a temporary location, and then - moved to their destinations. - """ - - # If a consistent snapshot is unneeded, 'file_object' may be simply moved - # 'compressed_filename' if not already written. - if not consistent_snapshot: - if write_new_metadata or not os.path.exists(compressed_filename): - file_object.move(compressed_filename) - - # The temporary file must be closed if 'file_object.move()' is not used. - # securesystemslib.util.TempFile() automatically closes the temp file when move() is - # called - else: - file_object.close_temp_file() - - # consistent snapshots = True. Ensure the version number is included in the - # compressed filename written, provided it does not already exist. - else: - compressed_content = file_object.read() - consistent_filename = None - version_and_filename = None - - # Attach the version number to the compressed, consistent snapshot filename. - dirname, basename = os.path.split(compressed_filename) - - for compression_extension in SUPPORTED_COMPRESSION_EXTENSIONS: - if basename.endswith(compression_extension): - basename = basename.split(compression_extension, 1)[0] - version_and_filename = str(version_number) + '.' + basename + compression_extension - consistent_filename = os.path.join(dirname, version_and_filename) - - else: - logger.debug('Skipping compression extension: ' + repr(compression_extension)) - - # Move the 'securesystemslib.util.TempFile' object to one of the filenames so that it is - # saved and the temporary file closed. - if not os.path.exists(consistent_filename): - logger.debug('Saving ' + repr(consistent_filename)) - file_object.move(consistent_filename) - - else: - logger.debug('Skipping already written compressed file:' - ' ' + repr(consistent_filename)) - - - - - def _log_status_of_top_level_roles(targets_directory, metadata_directory, repository_name): """ From 1edc4d4b8ac3d97cea7b7eb1c5b794794dcba91f Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 15:56:41 -0400 Subject: [PATCH 08/24] Remove compression from unit tests for formats.py, keydb.py, and roledb.py --- tests/test_formats.py | 6 ------ tests/test_keydb.py | 28 ++++++++++------------------ tests/test_roledb.py | 1 - 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/tests/test_formats.py b/tests/test_formats.py index 132051c1..c41bfa00 100755 --- a/tests/test_formats.py +++ b/tests/test_formats.py @@ -199,7 +199,6 @@ def test_schemas(self): {'_type': 'root', 'version': 8, 'consistent_snapshot': False, - 'compression_algorithms': ['gz'], 'expires': '1985-10-21T13:20:00Z', 'keys': {'123abc': {'keytype': 'rsa', 'scheme': 'rsassa-pss-sha256', @@ -351,8 +350,6 @@ def test_RootFile(self): 'threshold': 1, 'paths': ['path1/', 'path2']}} - compression_algorithms = ['gz'] - make_metadata = tuf.formats.RootFile.make_metadata from_metadata = tuf.formats.RootFile.from_metadata ROOT_SCHEMA = tuf.formats.ROOT_SCHEMA @@ -368,7 +365,6 @@ def test_RootFile(self): bad_expires = 'eight' bad_keydict = 123 bad_roledict = 123 - bad_compression_algorithms = ['nozip'] self.assertRaises(securesystemslib.exceptions.FormatError, make_metadata, bad_version, expires, keydict, roledict, consistent_snapshot) @@ -545,7 +541,6 @@ def test_make_signable(self): root = {'_type': 'root', 'version': 8, 'consistent_snapshot': False, - 'compression_algorithms': ['gz'], 'expires': '1985-10-21T13:20:00Z', 'keys': {'123abc': {'keytype': 'rsa', 'scheme': 'rsassa-pss-sha256', @@ -695,7 +690,6 @@ def test_check_signable_object_format(self): root = {'_type': 'root', 'version': 8, 'consistent_snapshot': False, - 'compression_algorithms': ['gz'], 'expires': '1985-10-21T13:20:00Z', 'keys': {'123abc': {'keytype': 'rsa', 'scheme': 'rsassa-pss-sha256', diff --git a/tests/test_keydb.py b/tests/test_keydb.py index d8b3971f..a061feb2 100755 --- a/tests/test_keydb.py +++ b/tests/test_keydb.py @@ -311,13 +311,9 @@ def test_create_keydb_from_root_metadata(self): version = 8 consistent_snapshot = False expires = '1985-10-21T01:21:00Z' - compression_algorithms = ['gz'] - root_metadata = tuf.formats.RootFile.make_metadata(version, - expires, - keydict, roledict, - consistent_snapshot, - compression_algorithms) + root_metadata = tuf.formats.RootFile.make_metadata(version, expires, + keydict, roledict, consistent_snapshot) self.assertEqual(None, tuf.keydb.create_keydb_from_root_metadata(root_metadata)) tuf.keydb.create_keydb_from_root_metadata(root_metadata) @@ -331,17 +327,17 @@ def test_create_keydb_from_root_metadata(self): # Test conditions for arguments with invalid formats. self.assertRaises(securesystemslib.exceptions.FormatError, - tuf.keydb.create_keydb_from_root_metadata, None) + tuf.keydb.create_keydb_from_root_metadata, None) self.assertRaises(securesystemslib.exceptions.FormatError, - tuf.keydb.create_keydb_from_root_metadata, '') + tuf.keydb.create_keydb_from_root_metadata, '') self.assertRaises(securesystemslib.exceptions.FormatError, - tuf.keydb.create_keydb_from_root_metadata, 123) + tuf.keydb.create_keydb_from_root_metadata, 123) self.assertRaises(securesystemslib.exceptions.FormatError, - tuf.keydb.create_keydb_from_root_metadata, ['123']) + tuf.keydb.create_keydb_from_root_metadata, ['123']) self.assertRaises(securesystemslib.exceptions.FormatError, - tuf.keydb.create_keydb_from_root_metadata, {'bad': '123'}) + tuf.keydb.create_keydb_from_root_metadata, {'bad': '123'}) self.assertRaises(securesystemslib.exceptions.FormatError, - tuf.keydb.create_keydb_from_root_metadata, root_metadata, 123) + tuf.keydb.create_keydb_from_root_metadata, root_metadata, 123) # Verify that a keydb cannot be created for a non-existent repository name. tuf.keydb.create_keydb_from_root_metadata(root_metadata, 'non-existent') @@ -367,13 +363,9 @@ def test_create_keydb_from_root_metadata(self): keydict[keyid3] = rsakey3 version = 8 expires = '1985-10-21T01:21:00Z' - compression_algorithms = ['gz'] - root_metadata = tuf.formats.RootFile.make_metadata(version, - expires, - keydict, roledict, - consistent_snapshot, - compression_algorithms) + root_metadata = tuf.formats.RootFile.make_metadata(version, expires, + keydict, roledict, consistent_snapshot) self.assertEqual(None, tuf.keydb.create_keydb_from_root_metadata(root_metadata)) # Ensure only 'keyid2' was added to the keydb database. 'keyid' and diff --git a/tests/test_roledb.py b/tests/test_roledb.py index eef9dea9..bb0d09e8 100755 --- a/tests/test_roledb.py +++ b/tests/test_roledb.py @@ -542,7 +542,6 @@ def test_create_roledb_from_root_metadata(self): version = 8 consistent_snapshot = False expires = '1985-10-21T01:21:00Z' - compression_algorithms = ['gz'] root_metadata = tuf.formats.RootFile.make_metadata(version, expires, keydict, roledict, consistent_snapshot) From 33721556ed8ec01c0354449033af93cac708a6fc Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 15:59:08 -0400 Subject: [PATCH 09/24] Do not generate compressed top-level repository data --- tests/repository_data/generate.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/repository_data/generate.py b/tests/repository_data/generate.py index 27975e5c..18064de7 100755 --- a/tests/repository_data/generate.py +++ b/tests/repository_data/generate.py @@ -135,13 +135,6 @@ repository.targets('role1').expiration = datetime.datetime(2030, 1, 1, 0, 0) repository.targets('role2').expiration = datetime.datetime(2030, 1, 1, 0, 0) -# Compress the top-level role metadata so that the unit tests have a -# pre-generated example of compressed metadata. -repository.root.compressions = ['gz'] -repository.targets.compressions = ['gz'] -repository.snapshot.compressions = ['gz'] -repository.timestamp.compressions = ['gz'] - # Create the actual metadata files, which are saved to 'metadata.staged'. if not options.dry_run: repository.writeall() From 134bf073a197061630e86b67c7dcc709754a43c5 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 16:13:05 -0400 Subject: [PATCH 10/24] Remove compression from repository tool and its unit test --- tests/test_repository_tool.py | 31 +-------- tuf/repository_tool.py | 115 +++------------------------------- 2 files changed, 13 insertions(+), 133 deletions(-) diff --git a/tests/test_repository_tool.py b/tests/test_repository_tool.py index a0494e8a..134a0374 100755 --- a/tests/test_repository_tool.py +++ b/tests/test_repository_tool.py @@ -227,7 +227,6 @@ def test_writeall(self): repository.targets('role1').load_signing_key(role1_privkey) # (6) Write repository. - repository.targets.compressions = ['gz'] repository.writeall() # Verify that the expected metadata is written. @@ -240,10 +239,6 @@ def test_writeall(self): self.assertTrue(os.path.exists(role_filepath)) - if role == 'targets.json': - compressed_filepath = role_filepath + '.gz' - self.assertTrue(os.path.exists(compressed_filepath)) - # Verify the 'role1.json' delegation is also written. role1_filepath = os.path.join(metadata_directory, 'role1.json') role1_signable = securesystemslib.util.load_json_file(role1_filepath) @@ -373,8 +368,7 @@ def test_writeall(self): self.assertEqual(['timestamp'], tuf.roledb.get_dirty_roles(repository_name)) # Test improperly formatted arguments. - self.assertRaises(securesystemslib.exceptions.FormatError, repository.writeall, 3, False) - self.assertRaises(securesystemslib.exceptions.FormatError, repository.writeall, False, 3) + self.assertRaises(securesystemslib.exceptions.FormatError, repository.writeall, 3) @@ -448,7 +442,7 @@ def __init__(self): roleinfo = {'keyids': [], 'signing_keyids': [], 'threshold': 1, 'signatures': [], 'version': 0, 'consistent_snapshot': False, - 'compressions': [''], 'expires': expiration, + 'expires': expiration, 'partial_loaded': False} tuf.roledb.add_role(self._rolename, roleinfo, @@ -573,24 +567,6 @@ def test_signing_keys(self): - def test_compressions(self): - # Test default case, where only uncompressed metadata is supported. - self.assertEqual(self.metadata.compressions, ['']) - - # Test compressions getter after a compressions algorithm is added. - self.metadata.compressions = ['gz'] - - self.assertEqual(self.metadata.compressions, ['', 'gz']) - - - # Test improperly formatted argument. - try: - self.metadata.compressions = 3 - except securesystemslib.exceptions.FormatError: - pass - else: - self.fail('Setter failed to detect improperly formatted compressions') - def test_add_verification_key(self): @@ -608,8 +584,7 @@ def test_add_verification_key(self): expiration = expiration.isoformat() + 'Z' roleinfo = {'keyids': [], 'signing_keyids': [], 'threshold': 1, 'signatures': [], 'version': 0, - 'consistent_snapshot': False, - 'compressions': [''], 'expires': expiration, + 'consistent_snapshot': False, 'expires': expiration, 'partial_loaded': False} tuf.roledb.add_role('Root', roleinfo, 'test_repository') diff --git a/tuf/repository_tool.py b/tuf/repository_tool.py index 9a041077..a77f8b45 100755 --- a/tuf/repository_tool.py +++ b/tuf/repository_tool.py @@ -186,7 +186,7 @@ def __init__(self, repository_directory, metadata_directory, - def writeall(self, consistent_snapshot=False, compression_algorithms=['gz']): + def writeall(self, consistent_snapshot=False): """ Write all the JSON Metadata objects to their corresponding files. @@ -202,11 +202,6 @@ def writeall(self, consistent_snapshot=False, compression_algorithms=['gz']): .README.json Example: 13.root.json' - compression_algorithms: - A list of compression algorithms. Each of these algorithms will be - used to compress all of the metadata available on the repository. - By default, all metadata is compressed with gzip. - tuf.exceptions.UnsignedMetadataError, if any of the top-level and delegated roles do not have the minimum threshold of signatures. @@ -224,7 +219,6 @@ def writeall(self, consistent_snapshot=False, compression_algorithms=['gz']): # 'securesystemslib.exceptions.FormatError' if any are improperly # formatted. securesystemslib.formats.BOOLEAN_SCHEMA.check_match(consistent_snapshot) - tuf.formats.COMPRESSIONS_SCHEMA.check_match(compression_algorithms) # At this point, tuf.keydb and tuf.roledb must be fully populated, # otherwise writeall() throws a 'tuf.exceptions.UnsignedMetadataError' for @@ -549,8 +543,8 @@ class Metadata(object): top-level roles: Root, Targets, Snapshot, and Timestamp. The Metadata class provides methods that are needed by all top-level roles, such as adding and removing public keys, private keys, and signatures. Metadata - attributes, such as rolename, version, threshold, expiration, key list, and - compressions, is also provided by the Metadata base class. + attributes, such as rolename, version, threshold, expiration, and key list + are also provided by the Metadata base class. None. @@ -1317,87 +1311,6 @@ def signing_keys(self): - @property - def compressions(self): - """ - - A getter method that returns a list of the file compression algorithms - used when the metadata is written to disk. If ['gz'] is set for the - 'targets.json' role, the metadata files 'targets.json' and - 'targets.json.gz' are written. - - >>> - >>> - >>> - - - None. - - - None. - - - None. - - - A list of compression algorithms, conformant to - 'tuf.formats.COMPRESSIONS_SCHEMA'. - """ - - roleinfo = tuf.roledb.get_roleinfo(self.rolename, self._repository_name) - compressions = roleinfo['compressions'] - - return compressions - - - - @compressions.setter - def compressions(self, compression_list): - """ - - A setter method for the file compression algorithms used when the - metadata is written to disk. If ['gz'] is set for the 'targets.json' role - the metadata files 'targets.json' and 'targets.json.gz' are written. - - >>> - >>> - >>> - - - compression_list: - A list of file compression algorithms, conformant to - 'tuf.formats.COMPRESSIONS_SCHEMA'. - - - securesystemslib.exceptions.FormatError, if 'compression_list' is - improperly formatted. - - - Updates the role's compression algorithms listed in 'tuf.roledb.py'. - - - None. - """ - - # Does 'compression_name' have the correct format? - # Ensure the arguments have the appropriate number of objects and object - # types, and that all dict keys are properly named. Raise - # 'securesystemslib.exceptions.FormatError' if any are improperly formatted. - tuf.formats.COMPRESSIONS_SCHEMA.check_match(compression_list) - - roleinfo = tuf.roledb.get_roleinfo(self.rolename, self._repository_name) - - # Add the compression algorithms of 'compression_list' to the role's - # entry in 'tuf.roledb.py'. - for compression in compression_list: - if compression not in roleinfo['compressions']: - roleinfo['compressions'].append(compression) - - tuf.roledb.update_roleinfo(self.rolename, roleinfo, - repository_name=self._repository_name) - - - class Root(Metadata): @@ -1452,8 +1365,7 @@ def __init__(self, repository_name): roleinfo = {'keyids': [], 'signing_keyids': [], 'threshold': 1, 'signatures': [], 'version': 0, 'consistent_snapshot': False, - 'compressions': [''], 'expires': expiration, - 'partial_loaded': False} + 'expires': expiration, 'partial_loaded': False} try: tuf.roledb.add_role(self._rolename, roleinfo, self._repository_name) @@ -1520,8 +1432,8 @@ def __init__(self, repository_name): expiration = expiration.isoformat() + 'Z' roleinfo = {'keyids': [], 'signing_keyids': [], 'threshold': 1, - 'signatures': [], 'version': 0, 'compressions': [''], - 'expires': expiration, 'partial_loaded': False} + 'signatures': [], 'version': 0, 'expires': expiration, + 'partial_loaded': False} try: tuf.roledb.add_role(self.rolename, roleinfo, self._repository_name) @@ -1583,8 +1495,8 @@ def __init__(self, repository_name): expiration = expiration.isoformat() + 'Z' roleinfo = {'keyids': [], 'signing_keyids': [], 'threshold': 1, - 'signatures': [], 'version': 0, 'compressions': [''], - 'expires': expiration, 'partial_loaded': False} + 'signatures': [], 'version': 0, 'expires': expiration, + 'partial_loaded': False} try: tuf.roledb.add_role(self._rolename, roleinfo, self._repository_name) @@ -1688,7 +1600,7 @@ def __init__(self, targets_directory, rolename='targets', roleinfo=None, # If 'roleinfo' is not provided, set an initial default. if roleinfo is None: roleinfo = {'keyids': [], 'signing_keyids': [], 'threshold': 1, - 'version': 0, 'compressions': [''], 'expires': expiration, + 'version': 0, 'expires': expiration, 'signatures': [], 'paths': {}, 'path_hash_prefixes': [], 'partial_loaded': False, 'delegations': {'keys': {}, 'roles': []}} @@ -2363,7 +2275,7 @@ def delegate(self, rolename, public_keys, list_of_targets, threshold=1, expiration = expiration.isoformat() + 'Z' roleinfo = {'name': rolename, 'keyids': keyids, 'signing_keyids': [], - 'threshold': threshold, 'version': 0, 'compressions': [''], + 'threshold': threshold, 'version': 0, 'expires': expiration, 'signatures': [], 'partial_loaded': False, 'paths': relative_targetpaths, 'delegations': {'keys': {}, 'roles': []}} @@ -3088,7 +3000,6 @@ def load_repository(repository_directory, repository_name='default'): 'signing_keyids': [], 'signatures': [], 'partial_loaded': False, - 'compressions': [], 'paths': {}, } @@ -3100,12 +3011,6 @@ def load_repository(repository_directory, repository_name='default'): roleinfo['paths'].update({filepath: fileinfo.get('custom', {})}) roleinfo['delegations'] = metadata_object['delegations'] - if os.path.exists(metadata_path + '.gz'): - roleinfo['compressions'].append('gz') - - else: - logger.debug('A compressed version does not exist.') - tuf.roledb.add_role(metadata_name, roleinfo, repository_name) loaded_metadata.append(metadata_name) From a602d449f3c847eb1ac1100a7a73b866fb9134fb Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 16:59:16 -0400 Subject: [PATCH 11/24] Remove compression from developer_tool.py --- tuf/developer_tool.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/tuf/developer_tool.py b/tuf/developer_tool.py index a39e4df5..b8463d69 100755 --- a/tuf/developer_tool.py +++ b/tuf/developer_tool.py @@ -134,9 +134,6 @@ # The full list of supported TUF metadata extensions. from tuf.repository_lib import METADATA_EXTENSIONS -# The recognized compression extensions. -from tuf.repository_lib import SUPPORTED_COMPRESSION_EXTENSIONS - # Supported key types. from tuf.repository_lib import SUPPORTED_KEY_TYPES @@ -525,9 +522,8 @@ def _generate_and_write_metadata(rolename, metadata_filename, write_partial, if tuf.sig.verify(signable, rolename, repository_name) or write_partial: _remove_invalid_and_duplicate_signatures(signable, repository_name) - compressions = roleinfo['compressions'] filename = write_metadata_file(signable, metadata_filename, - metadata['version'], compressions, False) + metadata['version'], False) # 'signable' contains an invalid threshold of signatures. else: @@ -912,7 +908,7 @@ def load_project(project_directory, prefix='', new_targets_location=None, for role in targets_metadata['delegations']['roles']: rolename = role['name'] roleinfo = {'name': role['name'], 'keyids': role['keyids'], - 'threshold': role['threshold'], 'compressions': [''], + 'threshold': role['threshold'], 'signing_keyids': [], 'signatures': [], 'partial_loaded':False, 'delegations': {'keys':{}, 'roles':[]} } @@ -967,9 +963,6 @@ def load_project(project_directory, prefix='', new_targets_location=None, roleinfo['delegations'] = metadata_object['delegations'] roleinfo['partial_loaded'] = False - if os.path.exists(metadata_path+'.gz'): - roleinfo['compressions'].append('gz') - # If the metadata was partially loaded, update the roleinfo flag. if _metadata_is_partially_loaded(metadata_name, signable, roleinfo, repository_name=repository_name): @@ -1003,8 +996,7 @@ def load_project(project_directory, prefix='', new_targets_location=None, rolename = role['name'] roleinfo = {'name': role['name'], 'keyids': role['keyids'], 'threshold': role['threshold'], - 'compressions': [''], 'signing_keyids': [], - 'signatures': [], + 'signing_keyids': [], 'signatures': [], 'partial_loaded': False, 'delegations': {'keys': {}, 'roles': []}} From bd754d595acd800943d3c14fb697c99a95da0ef4 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 16:59:41 -0400 Subject: [PATCH 12/24] Remove compression from updater.py and its unit test --- tests/test_updater.py | 18 ++---- tuf/client/updater.py | 127 +++++------------------------------------- 2 files changed, 20 insertions(+), 125 deletions(-) diff --git a/tests/test_updater.py b/tests/test_updater.py index 9bfd0ce3..a8fbf9c8 100755 --- a/tests/test_updater.py +++ b/tests/test_updater.py @@ -688,18 +688,16 @@ def test_3__update_metadata(self): # version is installed if the compressed one is downloaded. self.assertFalse('targets' in self.repository_updater.metadata['current']) self.repository_updater._update_metadata('targets', - DEFAULT_TARGETS_FILELENGTH, - targets_versioninfo['version'], - 'gzip') + DEFAULT_TARGETS_FILELENGTH, targets_versioninfo['version']) self.assertTrue('targets' in self.repository_updater.metadata['current']) self.assertEqual(targets_versioninfo['version'], - self.repository_updater.metadata['current']['targets']['version']) + self.repository_updater.metadata['current']['targets']['version']) # Test: Invalid / untrusted version numbers. # Invalid version number for the uncompressed version of 'targets.json'. self.assertRaises(tuf.exceptions.NoWorkingMirrorError, - self.repository_updater._update_metadata, - 'targets', DEFAULT_TARGETS_FILELENGTH, 88) + self.repository_updater._update_metadata, + 'targets', DEFAULT_TARGETS_FILELENGTH, 88) # Verify that the specific exception raised is correct for the previous # case. @@ -711,19 +709,13 @@ def test_3__update_metadata(self): for mirror_error in six.itervalues(e.mirror_errors): assert isinstance(mirror_error, securesystemslib.exceptions.BadVersionNumberError) - # Invalid version number for the compressed version of 'targets.json' - self.assertRaises(tuf.exceptions.NoWorkingMirrorError, - self.repository_updater._update_metadata, - 'targets', DEFAULT_TARGETS_FILELENGTH, 88, - 'gzip') - # Verify that the specific exception raised is correct for the previous # case. The version number is checked, so the specific error in # this case should be 'securesystemslib.exceptions.BadVersionNumberError'. try: self.repository_updater._update_metadata('targets', DEFAULT_TARGETS_FILELENGTH, - 88, 'gzip') + 88) except tuf.exceptions.NoWorkingMirrorError as e: for mirror_error in six.itervalues(e.mirror_errors): diff --git a/tuf/client/updater.py b/tuf/client/updater.py index a331ff36..6b495b7a 100755 --- a/tuf/client/updater.py +++ b/tuf/client/updater.py @@ -687,7 +687,7 @@ def refresh(self, unsafely_update_root_if_necessary=True): - def _update_root_metadata(self, current_root_metadata, compression_algorithm=None): + def _update_root_metadata(self, current_root_metadata): """ The root file must be signed by the current root threshold and keys as @@ -704,9 +704,6 @@ def _update_root_metadata(self, current_root_metadata, compression_algorithm=Non current_root_metadata: The currently held version of root. - compresison_algorithm: - The compression algorithm used to compress remote metadata. - Updates the root metadata files with the latest information. @@ -717,8 +714,7 @@ def _update_root_metadata(self, current_root_metadata, compression_algorithm=Non # Retrieve the latest, remote root.json. latest_root_metadata_file = \ self._get_metadata_file('root', 'root.json', - tuf.settings.DEFAULT_ROOT_REQUIRED_LENGTH, None, - compression_algorithm=compression_algorithm) + tuf.settings.DEFAULT_ROOT_REQUIRED_LENGTH, None) latest_root_metadata = \ securesystemslib.util.load_json_string(latest_root_metadata_file.read().decode('utf-8')) @@ -736,8 +732,8 @@ def _update_root_metadata(self, current_root_metadata, compression_algorithm=Non # in the latest root.json after running through the intermediates with # _update_metadata(). self.consistent_snapshot = True - self._update_metadata('root', tuf.settings.DEFAULT_ROOT_REQUIRED_LENGTH, version=version, - compression_algorithm=compression_algorithm) + self._update_metadata('root', tuf.settings.DEFAULT_ROOT_REQUIRED_LENGTH, + version=version) @@ -925,18 +921,13 @@ def verify_target_file(target_file_object): self._hard_check_file_length(target_file_object, file_length) self._check_hashes(target_file_object, file_hashes) - # Target files, unlike metadata files, are not decompressed; the - # 'compression' argument to _get_file() is needed only for decompression of - # metadata. Target files may be compressed or uncompressed. if self.consistent_snapshot: target_digest = random.choice(list(file_hashes.values())) dirname, basename = os.path.split(target_filepath) target_filepath = os.path.join(dirname, target_digest + '.' + basename) return self._get_file(target_filepath, verify_target_file, - 'target', file_length, compression=None, - verify_compressed_file_function=None, - download_safely=True) + 'target', file_length, download_safely=True) @@ -1015,8 +1006,7 @@ def _verify_uncompressed_metadata_file(self, metadata_file_object, def _get_metadata_file(self, metadata_role, remote_filename, - upperbound_filelength, expected_version, - compression_algorithm): + upperbound_filelength, expected_version): """ Non-public method that tries downloading, up to a certain length, a @@ -1039,10 +1029,6 @@ def _get_metadata_file(self, metadata_role, remote_filename, The expected and required version number of the 'metadata_role' file downloaded. 'expected_version' is an integer. - compression_algorithm: - The name of the compression algorithm (e.g., 'gzip'). The algorithm is - needed if the remote metadata file is compressed. - tuf.exceptions.NoWorkingMirrorError: The metadata could not be fetched. This is raised only when all known @@ -1068,13 +1054,6 @@ def _get_metadata_file(self, metadata_role, remote_filename, file_object = tuf.download.unsafe_download(file_mirror, upperbound_filelength) - if compression_algorithm is not None: - logger.info('Decompressing ' + str(file_mirror)) - file_object.decompress_temp_file_object(compression_algorithm) - - else: - logger.info('Not decompressing ' + str(file_mirror)) - # Verify 'file_object' according to the callable function. # 'file_object' is also verified if decompressed above (i.e., the # uncompressed version). @@ -1153,8 +1132,7 @@ def _verify_root_chain_link(self, role, current, next): def _get_file(self, filepath, verify_file_function, file_type, - file_length, compression=None, - verify_compressed_file_function=None, download_safely=True): + file_length, download_safely=True): """ Non-public method that tries downloading, up to a certain length, a @@ -1181,15 +1159,6 @@ def _get_file(self, filepath, verify_file_function, file_type, The expected length, or upper bound, of the target or metadata file to be downloaded. - compression: - The name of the compression algorithm (e.g., 'gzip'), if the metadata - file is compressed. - - verify_compressed_file_function: - If compression is specified, in the case of metadata files, this - callable function may be set to perform verification of the compressed - version of the metadata file. Decompressed metadata is also verified. - download_safely: A boolean switch to toggle safe or unsafe download of the file. @@ -1216,9 +1185,10 @@ def _get_file(self, filepath, verify_file_function, file_type, for file_mirror in file_mirrors: try: - # TODO: Instead of the more fragile 'download_safely' switch, unroll the - # function into two separate ones: one for "safe" download, and the other one - # for "unsafe" download? This should induce safer and more readable code. + # TODO: Instead of the more fragile 'download_safely' switch, unroll + # the function into two separate ones: one for "safe" download, and the + # other one for "unsafe" download? This should induce safer and more + # readable code. if download_safely: file_object = tuf.download.safe_download(file_mirror, file_length) @@ -1226,15 +1196,6 @@ def _get_file(self, filepath, verify_file_function, file_type, file_object = tuf.download.unsafe_download(file_mirror, file_length) - if compression is not None: - if verify_compressed_file_function is not None: - verify_compressed_file_function(file_object) - logger.info('Decompressing ' + str(file_mirror)) - file_object.decompress_temp_file_object(compression) - - else: - logger.info('Not decompressing ' + str(file_mirror)) - # Verify 'file_object' according to the callable function. # 'file_object' is also verified if decompressed above (i.e., the # uncompressed version). @@ -1261,8 +1222,7 @@ def _get_file(self, filepath, verify_file_function, file_type, - def _update_metadata(self, metadata_role, upperbound_filelength, version=None, - compression_algorithm=None): + def _update_metadata(self, metadata_role, upperbound_filelength, version=None): """ Non-public method that downloads, verifies, and 'installs' the metadata @@ -1284,12 +1244,6 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None, The expected and required version number of the 'metadata_role' file downloaded. 'expected_version' is an integer. - compression_algorithm: - A string designating the compression type of 'metadata_role'. - The 'snapshot' metadata file may be optionally downloaded and stored in - compressed form. Currently, only metadata files compressed with 'gzip' - are considered. Any other string is ignored. - tuf.exceptions.NoWorkingMirrorError: The metadata cannot be updated. This is not specific to a single @@ -1309,11 +1263,6 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None, metadata_filename = metadata_role + '.json' uncompressed_metadata_filename = metadata_filename - # The 'snapshot' or Targets metadata may be compressed. Add the appropriate - # extension to 'metadata_filename'. - if compression_algorithm == 'gzip': - metadata_filename = metadata_filename + '.gz' - # Attempt a file download from each mirror until the file is downloaded and # verified. If the signature of the downloaded file is valid, proceed, # otherwise log a warning and try the next mirror. 'metadata_file_object' @@ -1329,10 +1278,6 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None, # for each other. In this case, we will download the metadata up to the # best length we can get for it, not request a specific version, but # perform the rest of the checks (e.g., signature verification). - # - # Note also that we presently support decompression of only "safe" - # metadata, but this is easily extend to "unsafe" metadata as well as - # "safe" targets. remote_filename = metadata_filename filename_version = '' @@ -1344,8 +1289,7 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None, metadata_file_object = \ self._get_metadata_file(metadata_role, remote_filename, - upperbound_filelength, version, - compression_algorithm) + upperbound_filelength, version) # The metadata has been verified. Move the metadata file into place. # First, move the 'current' metadata file to the 'previous' directory @@ -1370,16 +1314,7 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None, metadata_signable = \ securesystemslib.util.load_json_string(metadata_file_object.read().decode('utf-8')) - if compression_algorithm == 'gzip': - current_uncompressed_filepath = \ - os.path.join(self.metadata_directory['current'], - uncompressed_metadata_filename) - current_uncompressed_filepath = \ - os.path.abspath(current_uncompressed_filepath) - metadata_file_object.move(current_uncompressed_filepath) - - else: - metadata_file_object.move(current_filepath) + metadata_file_object.move(current_filepath) # Extract the metadata object so we can store it to the metadata store. # 'current_metadata_object' set to 'None' if there is not an object @@ -1512,38 +1447,6 @@ def _update_metadata_if_changed(self, metadata_role, logger.debug('Metadata ' + repr(uncompressed_metadata_filename) + ' has changed.') - # There might be a compressed version of 'snapshot.json' or Targets - # metadata available for download. Check the 'meta' field of - # 'referenced_metadata' to see if it is listed when 'metadata_role' - # is 'snapshot'. The full rolename for delegated Targets metadata - # must begin with 'targets/'. The snapshot role lists all the Targets - # metadata available on the repository, including any that may be in - # compressed form. - # - # In addition to validating the fileinfo (i.e., file lengths and hashes) - # of the uncompressed metadata, the compressed version is also verified to - # match its respective fileinfo. Verifying the compressed fileinfo ensures - # untrusted data is not decompressed prior to verifying hashes, or - # decompressing a file that may be invalid or partially intact. - compression = None - - # Check for the availability of compressed versions of 'snapshot.json', - # 'targets.json', and delegated Targets (that also start with 'targets'). - # For 'targets.json' and delegated metadata, 'referenced_metata' - # should always be 'snapshot'. 'snapshot.json' specifies all roles - # provided by a repository, including their version numbers. - if metadata_role == 'snapshot' or metadata_role.startswith('targets'): - if 'gzip' in self.metadata['current']['root']['compression_algorithms']: - compression = 'gzip' - gzip_metadata_filename = uncompressed_metadata_filename + '.gz' - logger.debug('Compressed version of ' + - repr(uncompressed_metadata_filename) + ' is available at ' + - repr(gzip_metadata_filename) + '.') - - else: - logger.debug('Compressed version of ' + - repr(uncompressed_metadata_filename) + ' not available.') - # The file lengths of metadata are unknown, only their version numbers are # known. Set an upper limit for the length of the downloaded file for each # expected role. Note: The Timestamp role is not updated via this @@ -1560,7 +1463,7 @@ def _update_metadata_if_changed(self, metadata_role, try: self._update_metadata(metadata_role, upperbound_filelength, - expected_versioninfo['version'], compression) + expected_versioninfo['version']) except: # The current metadata we have is not current but we couldn't get new From d5f933b18d0b4141fcc7cb0880179cf6624d877e Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 17:04:50 -0400 Subject: [PATCH 13/24] Remove compression from developer_tool.py's unit test --- tests/test_developer_tool.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/test_developer_tool.py b/tests/test_developer_tool.py index b4dded4d..a21dd0d0 100755 --- a/tests/test_developer_tool.py +++ b/tests/test_developer_tool.py @@ -347,10 +347,6 @@ def test_write(self): # + backup the name. name_backup = project._project_name - # Set the compressions. We will be checking this part here too. - project.compressions = ['gz'] - project('delegation').compressions = project.compressions - # Write and reload. self.assertRaises(securesystemslib.exceptions.Error, project.write) project.write(write_partial=True) From 15777a309f4ad38f5e5754f1f5acea568e2b3eda Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 17:16:12 -0400 Subject: [PATCH 14/24] Remove compression from test_root_versioning_integration.py --- tests/test_root_versioning_integration.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_root_versioning_integration.py b/tests/test_root_versioning_integration.py index 790706fd..c68a9d8f 100755 --- a/tests/test_root_versioning_integration.py +++ b/tests/test_root_versioning_integration.py @@ -179,7 +179,6 @@ def test_root_role_versioning(self): repository.targets('role1').load_signing_key(role1_privkey) # (6) Write repository. - repository.targets.compressions = ['gz'] repository.writeall() self.assertTrue(os.path.exists(os.path.join(metadata_directory, 'root.json'))) From b7c3b7c1982e6831a1a5ccdb519b2bcf38fcdb42 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 17:25:32 -0400 Subject: [PATCH 15/24] Fix remaining unit test failures for repository_tool.py --- tests/test_repository_tool.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/tests/test_repository_tool.py b/tests/test_repository_tool.py index 134a0374..a6a48320 100755 --- a/tests/test_repository_tool.py +++ b/tests/test_repository_tool.py @@ -382,11 +382,9 @@ def test_get_filepaths_in_directory(self): # Verify the expected filenames. get_filepaths_in_directory() returns # a list of absolute paths. metadata_files = repo.get_filepaths_in_directory(metadata_directory) - expected_files = ['1.root.json', '1.root.json.gz', 'root.json', - 'targets.json', 'targets.json.gz', 'snapshot.json', - 'snapshot.json.gz', 'timestamp.json', - 'timestamp.json.gz', 'role1.json', 'role1.json.gz', - 'role2.json', 'role2.json.gz'] + expected_files = ['1.root.json', 'root.json', + 'targets.json', 'snapshot.json', + 'timestamp.json', 'role1.json', 'role2.json'] basenames = [] for filepath in metadata_files: @@ -1683,11 +1681,6 @@ def test_load_repository(self): with open(bad_root_content, 'wb') as file_object: file_object.write(b'bad') - # Remove the compressed version of role1 to test whether the - # load_repository() complains or not (it logs a message). - role1_path = os.path.join(metadata_directory, 'role1.json.gz') - os.remove(role1_path) - repository = repo_tool.load_repository(repository_directory) self.assertTrue(isinstance(repository, repo_tool.Repository)) From 419569c6d6d1c4fbd9dace384d4be8161517e50f Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Fri, 25 Aug 2017 17:26:02 -0400 Subject: [PATCH 16/24] Re-generate metadata that doesn't reference compressed metadata --- .../metadata/current/1.root.json | Bin 3412 -> 3369 bytes .../metadata/current/1.root.json.gz | Bin 1690 -> 0 bytes .../metadata/current/role1.json.gz | Bin 618 -> 0 bytes .../metadata/current/role2.json.gz | Bin 287 -> 0 bytes .../metadata/current/root.json | Bin 3412 -> 3369 bytes .../metadata/current/snapshot.json.gz | Bin 305 -> 0 bytes .../metadata/current/targets.json.gz | Bin 815 -> 0 bytes .../metadata/current/timestamp.json.gz | Bin 357 -> 0 bytes .../metadata/previous/1.root.json | Bin 3412 -> 3369 bytes .../metadata/previous/role1.json.gz | Bin 618 -> 0 bytes .../metadata/previous/role2.json.gz | Bin 287 -> 0 bytes .../metadata/previous/root.json | Bin 3412 -> 3369 bytes .../metadata/previous/snapshot.json.gz | Bin 305 -> 0 bytes .../metadata/previous/targets.json.gz | Bin 815 -> 0 bytes .../metadata/previous/timestamp.json.gz | Bin 357 -> 0 bytes .../project/test-flat/test-flat.json | Bin 2197 -> 2197 bytes .../project/test-flat/test-flat.json.gz | Bin 1173 -> 0 bytes .../repository/metadata.staged/1.root.json | Bin 3412 -> 3369 bytes .../repository/metadata.staged/1.root.json.gz | Bin 1690 -> 0 bytes .../repository/metadata.staged/role1.json.gz | Bin 618 -> 0 bytes .../repository/metadata.staged/role2.json.gz | Bin 287 -> 0 bytes .../repository/metadata.staged/root.json | Bin 3412 -> 3369 bytes .../metadata.staged/snapshot.json.gz | Bin 305 -> 0 bytes .../metadata.staged/targets.json.gz | Bin 815 -> 0 bytes .../metadata.staged/timestamp.json.gz | Bin 357 -> 0 bytes .../repository/metadata/1.root.json | Bin 3412 -> 3369 bytes .../repository/metadata/1.root.json.gz | Bin 1690 -> 0 bytes .../repository/metadata/role1.json.gz | Bin 618 -> 0 bytes .../repository/metadata/role2.json.gz | Bin 287 -> 0 bytes .../repository/metadata/root.json | Bin 3412 -> 3369 bytes .../repository/metadata/snapshot.json.gz | Bin 305 -> 0 bytes .../repository/metadata/targets.json.gz | Bin 815 -> 0 bytes .../repository/metadata/timestamp.json.gz | Bin 357 -> 0 bytes 33 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/repository_data/client/test_repository/metadata/current/1.root.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/current/role1.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/current/role2.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/current/snapshot.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/current/targets.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/current/timestamp.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/previous/role1.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/previous/role2.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/previous/snapshot.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/previous/targets.json.gz delete mode 100644 tests/repository_data/client/test_repository/metadata/previous/timestamp.json.gz delete mode 100644 tests/repository_data/project/test-flat/test-flat.json.gz delete mode 100644 tests/repository_data/repository/metadata.staged/1.root.json.gz delete mode 100644 tests/repository_data/repository/metadata.staged/role1.json.gz delete mode 100644 tests/repository_data/repository/metadata.staged/role2.json.gz delete mode 100644 tests/repository_data/repository/metadata.staged/snapshot.json.gz delete mode 100644 tests/repository_data/repository/metadata.staged/targets.json.gz delete mode 100644 tests/repository_data/repository/metadata.staged/timestamp.json.gz delete mode 100644 tests/repository_data/repository/metadata/1.root.json.gz delete mode 100644 tests/repository_data/repository/metadata/role1.json.gz delete mode 100644 tests/repository_data/repository/metadata/role2.json.gz delete mode 100644 tests/repository_data/repository/metadata/snapshot.json.gz delete mode 100644 tests/repository_data/repository/metadata/targets.json.gz delete mode 100644 tests/repository_data/repository/metadata/timestamp.json.gz diff --git a/tests/repository_data/client/test_repository/metadata/current/1.root.json b/tests/repository_data/client/test_repository/metadata/current/1.root.json index f6998b4bbbe971cfff8e14a77e8329374980200f..79e296739fe947d388b9dc25176ae772fda6074b 100644 GIT binary patch delta 790 zcmWlXyA5td41@zDBwDyl;P-mV@oNjX4g4t~5>*h>1|bFE|3oVt%bxjW{`>Lwk3WBY zqCuDfbxI6Lu|;pE5RN=jsW|Z@i9P7}*%f`#EDG&Cml!04 zh1Clg5$f%rP*G5cP=Dq^V(>Jbijv|wNMU)86y~|Er@%ycR7v<`T!mA+90Dii+<=<` zA$=0erU)BcWcJ{xLg{{SzIHeg<{Y)roK(lvh)mnjkaeatCe7cAs#P-!0=SE>1&J0;-v@r2clFMEeDWGZy}O_s zSksMF;YCnOIk&uqxFU`$D~qFJ80g*jIu){-jL>FlG`jmZH+9A8x)_$|g_rVhCqlvP z6oMk>^Nx>Ey|J5kB3IoFdGBSTYrU#%04+A_t;jlmayN4hEG$dNlk^DAw*g4zWkMmm z3ibQ1;W{F(_{BzXB;vl1jM;)c%<{kwZFIhtXwN>=U|!PaZTwm>>Lw!jmjDtOJ0NB&EQspp2G>51 z@A#kh|Goe7<-t|b+h{$~k6n=Zh6+3j=~2YWY&*e14kXp`1>Gq($Xbq5k5X9j!i2lV zjnRXTlrKx_WpbBz8PNh?F-J3@NcM%DWZAN0?;RVa#on1VG_;{F>?La5EWhJ1BJoCQRs3$1`|cuPx@Q z31fuT{XkeF?lsldxmKhDkId_u-JQWT;FecvK#wS=si#V$C1lTN+vygZ&MW5IH*u36 znMv=0=-P+sh#{+??lTa>#3t$J4gWDo&NsX2g@tdG+aV?m(niaUuyHu`h=pkx| zN6~nGhKok*0#pOrz9#0{N7z(721}h>(dlw)1I4$Hgo}QjR{Qf-OAOHRP I-5+2755lkK`~Uy| diff --git a/tests/repository_data/client/test_repository/metadata/current/1.root.json.gz b/tests/repository_data/client/test_repository/metadata/current/1.root.json.gz deleted file mode 100644 index 5d5913af0a2c46f2bbdb434d881bdd4061adacdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1690 zcmV;L24(pliwFqgkDOTm12HagZ*O!iYIARH0L@m{ZX3xGeb-kIe3cD#4hHst98pvv zMNxs0uMDF@HS;jcD3A;P`_@RZ*1Oo?3-97yVhE7kJrz#Xsnb92)au1}n7i_R4MqJ! z?LRxU+Ryl{)u*r-M_j23&{{_zk!hK1WJVejqjgjf6@nH9q%g?>V_s=1y$+ry#gjFJ z%M^V5-LpM(Q(5BxGVzoQp=d+^m0D^rK%~&l8x97I5CEYF30?zOVr)`OIpZnlq?J=# zt7Hk+7UOb~o2U&VjxcMJ{M0R-iLZec(od7cR0SoU}rEaEuA!MZlvm5@1qUq9SuKNgD&gcwz+fm-)J1%WVnvd*LQ5+ZNeHK-)M)BBZU!%P2nq<* zjyUB7Mk$n$+-dCtf&wOrkfN6s6k%8&sj;6dAyV@yaBg&P8uw*lhF~I|1w`0shoC^B z5+QPgIG0$89MeQltW}I^hQL$Gv`9V%320L|6A0psEddpB$y>yl8>XW~P9R@s;4xtl z2*qlHPoCR4lHtov?bEwg=0U}=igESNceei?bGYgycicHnZc>ikXb(DM_xnlGOSyZE8Q%q^$n@@6)?C6L0VouKw%lgPXlM zs@0eGel`x(srS{V*=iqkYrU)H=}}fYY27|A-sPR6qvm4L=r)Jb)o40y+egxDoVN}d zjkBzAYZ}%5czA-pTMg2l^cL6a$%Tb%wOyQ>>ptA&y=g|mk(!p{)^OEJhpmf)?dEAS z$%G}@{f657{;3y^??0xl5}iz##o4sKJ7DvbSau{G-{nv9*p^R|hwfRkKRuR@S6MJ= zKbw`EtIOtWRoab&(<1GOz1E_6wY$y4#ej}`SG&9OtQeP@yF8tr>nnA7mh;wawpmXP zB^`a-iw`H6SlG+nZRh%_3*ne&r*uWwITiAFwwW|9?>qb^t_pXT=kfAzadXk{&F9-; zbC1T;y&%pfojhASu1^L;%@0mjw%@pIAGzZ}>g_0u^mxJkvyfSp7`{m@cq?=;u2RF?le|CMBZ>?zG z6vNH7(cNU1cGaI8-t6yh*?fAs+O0tY)jJUna z`$9j$P27jj>pl%O7(hh;cz}!j<$IgWxQ#RdfiEC z+~v-&P50o|-243O>iYOBk^H7T(lG z`~G@q+%K;!T7(hIzxHiWxcAGVc>mh)J8$Re5~oB=#w9}ySRBAOl!;a%;0V)Rpww8& zoFkEH>yc}Q3!Ho!Rg4p+P5igWhKeI4wckNFhyg{FGe>j`zKz-#B0B0=MAfgNL&tUr+!8c$ji88??bry}Ix_C|nN+ji|a>1jdpg=?rIFc;} zp%5&cKnP1ciU6_ve-9R3X_)a*Km-YaYonaEsHKrgk+`iUEhENIyybwhLHkOnB&xU4 zk{Bxg3$To%L7;fz4M9>FAy~t_vzC$|Q^anv)PY3InDjQJ#AGDOCsbEj-Ac^=0az@A zq#U+8vnD0MeR3p3#jQ~W?;XGi-mDNM1TYay5-&DjjZ}b4@kx9aSUayLPaTi&@2H`b`PH5%fO`@OzU+MY1@*gU{!|SB06MTn^8f$< diff --git a/tests/repository_data/client/test_repository/metadata/current/role1.json.gz b/tests/repository_data/client/test_repository/metadata/current/role1.json.gz deleted file mode 100644 index 4b9ff54595ccf99b4f7cc0808c48bed080750b1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 618 zcmV-w0+szAiwFSXkDOTo|E*KYZrd;ry!$H*ozs?FzVjVDwFrXca%l-sY{OE51cCp( ztB38R*H(}KQKWWfW@kP&+h*u?dmLX*JT&*)-<$3BL!NE(#P3~^FAYTnP*HQri87dk zJ{u1?ms&A-o7ihCK-s5MfNdsQOAW~=RO~G_cXK^yGgYg>hFS8e93)B z^JrucVA;8f0A4wdBBwT7HD^lA;e<`%b1=!RduHqbVZ0EMub0eRgJ4r{kpUhjaANab}N@ChW zKlw-Bh&^mpat*&7yCqZ&D5Jh9E%#5Q?&tg0Vy}zWF4p={yPnPW@ol^rZ1MvSpKP+a zKniQCB~Yq56QVAf(AgZ(DU?Z4mMylHKx0Z#hKdoDLqq~n3S#v6N_{obG^^?|qiF4w z)tO3xWP+ApR?fvn2gy@$wgzJ(%NtsWs3VnvOJ2po)&~qoinEi1o1(x%kw_Xc%5lsx zu>#gvL>sHMHma%}S7d=NabHcc0Bd^Q@5WYeLENkoFY3PXX^>DZ;-5F?Kil`@YRUuv E06!NjMgRZ+ diff --git a/tests/repository_data/client/test_repository/metadata/current/role2.json.gz b/tests/repository_data/client/test_repository/metadata/current/role2.json.gz deleted file mode 100644 index 6be24b7870f8b4bb48397fd371bd7e61cac2c3d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmV+)0pR{0iwFSYkDOTo|20rcYQsPb-TM?~)+x;2qnx9wmQW;(#+ZgA*luYEzI(@Z z0@6Z4dcQ~0s%hviIRA_?sbl-uwC$sItG?wv$)y9QQA_lw4jW#jSt%W#ZqaPRvO62E=RLdAioJcw-)-0fRaQIw lrcJGPt&dxM?9eZs7n1swajHahVVWv(`3FE~jtrgw000)?i^2c^ diff --git a/tests/repository_data/client/test_repository/metadata/current/root.json b/tests/repository_data/client/test_repository/metadata/current/root.json index f6998b4bbbe971cfff8e14a77e8329374980200f..79e296739fe947d388b9dc25176ae772fda6074b 100644 GIT binary patch delta 790 zcmWlXyA5td41@zDBwDyl;P-mV@oNjX4g4t~5>*h>1|bFE|3oVt%bxjW{`>Lwk3WBY zqCuDfbxI6Lu|;pE5RN=jsW|Z@i9P7}*%f`#EDG&Cml!04 zh1Clg5$f%rP*G5cP=Dq^V(>Jbijv|wNMU)86y~|Er@%ycR7v<`T!mA+90Dii+<=<` zA$=0erU)BcWcJ{xLg{{SzIHeg<{Y)roK(lvh)mnjkaeatCe7cAs#P-!0=SE>1&J0;-v@r2clFMEeDWGZy}O_s zSksMF;YCnOIk&uqxFU`$D~qFJ80g*jIu){-jL>FlG`jmZH+9A8x)_$|g_rVhCqlvP z6oMk>^Nx>Ey|J5kB3IoFdGBSTYrU#%04+A_t;jlmayN4hEG$dNlk^DAw*g4zWkMmm z3ibQ1;W{F(_{BzXB;vl1jM;)c%<{kwZFIhtXwN>=U|!PaZTwm>>Lw!jmjDtOJ0NB&EQspp2G>51 z@A#kh|Goe7<-t|b+h{$~k6n=Zh6+3j=~2YWY&*e14kXp`1>Gq($Xbq5k5X9j!i2lV zjnRXTlrKx_WpbBz8PNh?F-J3@NcM%DWZAN0?;RVa#on1VG_;{F>?La5EWhJ1BJoCQRs3$1`|cuPx@Q z31fuT{XkeF?lsldxmKhDkId_u-JQWT;FecvK#wS=si#V$C1lTN+vygZ&MW5IH*u36 znMv=0=-P+sh#{+??lTa>#3t$J4gWDo&NsX2g@tdG+aV?m(niaUuyHu`h=pkx| zN6~nGhKok*0#pOrz9#0{N7z(721}h>(dlw)1I4$Hgo}QjR{Qf-OAOHRP I-5+2755lkK`~Uy| diff --git a/tests/repository_data/client/test_repository/metadata/current/snapshot.json.gz b/tests/repository_data/client/test_repository/metadata/current/snapshot.json.gz deleted file mode 100644 index b482985be0979a897137f82e06a42adfb0f883cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmV-10nYv(iwFSYkDOTo|BaB%PQx$|gztF@%jbe@XE(O{9GpN1t-b3Kewr!?h^orF zlcWWS6P4DN*-x`GK2=H&?QT!wM=yiks)tIc)BKcvm1E1ZqA?P12~>g&5`{e_F}{Ip z68HoTOhiXy*!q|-`A|cX!5hl8aXzr#tbX&E#mzz?pMnW4Wfm02nJ^{Cv5oL8+EnkQB{5RT}+T0jB&z&*bb?(p5yNq=4 zQM&Km#NNIP-Tp^X`cwL$T?M-c)8?0SSCZX$6*yAAlX3WmtuFlE#Z*n-VWGLf5dr`J DW1W?8 diff --git a/tests/repository_data/client/test_repository/metadata/current/targets.json.gz b/tests/repository_data/client/test_repository/metadata/current/targets.json.gz deleted file mode 100644 index 0f54614b8db1ec7b44b88f7497b5db7253ec9c06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 815 zcmV+~1JL{*iwFSYkDOTo|D{w-kK;BBz2{d1K2KXxq&~R6qo)>w0VPqBpqV6yJ&Ro| z=D$~VJekR&?WKl&utbsXJw5WrW;=}g=c7)q7aNB!+dntk?T`L#hrjImzV?+Nc#P;g zs%UFoQzm56gv1F;hS-8ZHMWcrOAIklY{o2@BMAr%4@GtPxuZBYmmEU?}(t(rgWblg4Z;rVpgPrH}* zTUi3eojM<`imv}27f$_oeE3N7&c&+p9%cBn^;HiaCAY)*H6Qk6j%}qm$L4+0t|R!M zwIPxc5kc6VieYx{%IuhX~b=LC~oUiQ6h_Q%=PO%J2pwsyUhcBjK^ zEc{^nxLH{b_U*jCcH7{9;1|ID{tobEdH=Zj?%jm%o?D>c0_DSbuj6!j`Q)ED=IJ~` z8^_hLLttKYzXBX)d)fHu)M~1w)pIH#w%(2+RFfpd_vQ`K`ZTGPUEzStsSk`8 zTIpk>d6!rS6RGZ& z!mf5VcjYB|f@a=Tj%HLNcgDeMD-}5>A0s8BkV_xa+AQk_N@} zFxxObp6<yg~(>vg_;jFv<9h}>}`zE#&cCZ!)1j*YV)t7=^nzI-^X!eq8PalOjd#kb4 zT*=wy61Nr@s6`CsAa1AIqCa|hTBpt>oA1&;eOcxs4DP}<+}-~_Y{T{eM;W*h>1|bFE|3oVt%bxjW{`>Lwk3WBY zqCuDfbxI6Lu|;pE5RN=jsW|Z@i9P7}*%f`#EDG&Cml!04 zh1Clg5$f%rP*G5cP=Dq^V(>Jbijv|wNMU)86y~|Er@%ycR7v<`T!mA+90Dii+<=<` zA$=0erU)BcWcJ{xLg{{SzIHeg<{Y)roK(lvh)mnjkaeatCe7cAs#P-!0=SE>1&J0;-v@r2clFMEeDWGZy}O_s zSksMF;YCnOIk&uqxFU`$D~qFJ80g*jIu){-jL>FlG`jmZH+9A8x)_$|g_rVhCqlvP z6oMk>^Nx>Ey|J5kB3IoFdGBSTYrU#%04+A_t;jlmayN4hEG$dNlk^DAw*g4zWkMmm z3ibQ1;W{F(_{BzXB;vl1jM;)c%<{kwZFIhtXwN>=U|!PaZTwm>>Lw!jmjDtOJ0NB&EQspp2G>51 z@A#kh|Goe7<-t|b+h{$~k6n=Zh6+3j=~2YWY&*e14kXp`1>Gq($Xbq5k5X9j!i2lV zjnRXTlrKx_WpbBz8PNh?F-J3@NcM%DWZAN0?;RVa#on1VG_;{F>?La5EWhJ1BJoCQRs3$1`|cuPx@Q z31fuT{XkeF?lsldxmKhDkId_u-JQWT;FecvK#wS=si#V$C1lTN+vygZ&MW5IH*u36 znMv=0=-P+sh#{+??lTa>#3t$J4gWDo&NsX2g@tdG+aV?m(niaUuyHu`h=pkx| zN6~nGhKok*0#pOrz9#0{N7z(721}h>(dlw)1I4$Hgo}QjR{Qf-OAOHRP I-5+2755lkK`~Uy| diff --git a/tests/repository_data/client/test_repository/metadata/previous/role1.json.gz b/tests/repository_data/client/test_repository/metadata/previous/role1.json.gz deleted file mode 100644 index 4b9ff54595ccf99b4f7cc0808c48bed080750b1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 618 zcmV-w0+szAiwFSXkDOTo|E*KYZrd;ry!$H*ozs?FzVjVDwFrXca%l-sY{OE51cCp( ztB38R*H(}KQKWWfW@kP&+h*u?dmLX*JT&*)-<$3BL!NE(#P3~^FAYTnP*HQri87dk zJ{u1?ms&A-o7ihCK-s5MfNdsQOAW~=RO~G_cXK^yGgYg>hFS8e93)B z^JrucVA;8f0A4wdBBwT7HD^lA;e<`%b1=!RduHqbVZ0EMub0eRgJ4r{kpUhjaANab}N@ChW zKlw-Bh&^mpat*&7yCqZ&D5Jh9E%#5Q?&tg0Vy}zWF4p={yPnPW@ol^rZ1MvSpKP+a zKniQCB~Yq56QVAf(AgZ(DU?Z4mMylHKx0Z#hKdoDLqq~n3S#v6N_{obG^^?|qiF4w z)tO3xWP+ApR?fvn2gy@$wgzJ(%NtsWs3VnvOJ2po)&~qoinEi1o1(x%kw_Xc%5lsx zu>#gvL>sHMHma%}S7d=NabHcc0Bd^Q@5WYeLENkoFY3PXX^>DZ;-5F?Kil`@YRUuv E06!NjMgRZ+ diff --git a/tests/repository_data/client/test_repository/metadata/previous/role2.json.gz b/tests/repository_data/client/test_repository/metadata/previous/role2.json.gz deleted file mode 100644 index 6be24b7870f8b4bb48397fd371bd7e61cac2c3d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmV+)0pR{0iwFSYkDOTo|20rcYQsPb-TM?~)+x;2qnx9wmQW;(#+ZgA*luYEzI(@Z z0@6Z4dcQ~0s%hviIRA_?sbl-uwC$sItG?wv$)y9QQA_lw4jW#jSt%W#ZqaPRvO62E=RLdAioJcw-)-0fRaQIw lrcJGPt&dxM?9eZs7n1swajHahVVWv(`3FE~jtrgw000)?i^2c^ diff --git a/tests/repository_data/client/test_repository/metadata/previous/root.json b/tests/repository_data/client/test_repository/metadata/previous/root.json index f6998b4bbbe971cfff8e14a77e8329374980200f..79e296739fe947d388b9dc25176ae772fda6074b 100644 GIT binary patch delta 790 zcmWlXyA5td41@zDBwDyl;P-mV@oNjX4g4t~5>*h>1|bFE|3oVt%bxjW{`>Lwk3WBY zqCuDfbxI6Lu|;pE5RN=jsW|Z@i9P7}*%f`#EDG&Cml!04 zh1Clg5$f%rP*G5cP=Dq^V(>Jbijv|wNMU)86y~|Er@%ycR7v<`T!mA+90Dii+<=<` zA$=0erU)BcWcJ{xLg{{SzIHeg<{Y)roK(lvh)mnjkaeatCe7cAs#P-!0=SE>1&J0;-v@r2clFMEeDWGZy}O_s zSksMF;YCnOIk&uqxFU`$D~qFJ80g*jIu){-jL>FlG`jmZH+9A8x)_$|g_rVhCqlvP z6oMk>^Nx>Ey|J5kB3IoFdGBSTYrU#%04+A_t;jlmayN4hEG$dNlk^DAw*g4zWkMmm z3ibQ1;W{F(_{BzXB;vl1jM;)c%<{kwZFIhtXwN>=U|!PaZTwm>>Lw!jmjDtOJ0NB&EQspp2G>51 z@A#kh|Goe7<-t|b+h{$~k6n=Zh6+3j=~2YWY&*e14kXp`1>Gq($Xbq5k5X9j!i2lV zjnRXTlrKx_WpbBz8PNh?F-J3@NcM%DWZAN0?;RVa#on1VG_;{F>?La5EWhJ1BJoCQRs3$1`|cuPx@Q z31fuT{XkeF?lsldxmKhDkId_u-JQWT;FecvK#wS=si#V$C1lTN+vygZ&MW5IH*u36 znMv=0=-P+sh#{+??lTa>#3t$J4gWDo&NsX2g@tdG+aV?m(niaUuyHu`h=pkx| zN6~nGhKok*0#pOrz9#0{N7z(721}h>(dlw)1I4$Hgo}QjR{Qf-OAOHRP I-5+2755lkK`~Uy| diff --git a/tests/repository_data/client/test_repository/metadata/previous/snapshot.json.gz b/tests/repository_data/client/test_repository/metadata/previous/snapshot.json.gz deleted file mode 100644 index b482985be0979a897137f82e06a42adfb0f883cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmV-10nYv(iwFSYkDOTo|BaB%PQx$|gztF@%jbe@XE(O{9GpN1t-b3Kewr!?h^orF zlcWWS6P4DN*-x`GK2=H&?QT!wM=yiks)tIc)BKcvm1E1ZqA?P12~>g&5`{e_F}{Ip z68HoTOhiXy*!q|-`A|cX!5hl8aXzr#tbX&E#mzz?pMnW4Wfm02nJ^{Cv5oL8+EnkQB{5RT}+T0jB&z&*bb?(p5yNq=4 zQM&Km#NNIP-Tp^X`cwL$T?M-c)8?0SSCZX$6*yAAlX3WmtuFlE#Z*n-VWGLf5dr`J DW1W?8 diff --git a/tests/repository_data/client/test_repository/metadata/previous/targets.json.gz b/tests/repository_data/client/test_repository/metadata/previous/targets.json.gz deleted file mode 100644 index 0f54614b8db1ec7b44b88f7497b5db7253ec9c06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 815 zcmV+~1JL{*iwFSYkDOTo|D{w-kK;BBz2{d1K2KXxq&~R6qo)>w0VPqBpqV6yJ&Ro| z=D$~VJekR&?WKl&utbsXJw5WrW;=}g=c7)q7aNB!+dntk?T`L#hrjImzV?+Nc#P;g zs%UFoQzm56gv1F;hS-8ZHMWcrOAIklY{o2@BMAr%4@GtPxuZBYmmEU?}(t(rgWblg4Z;rVpgPrH}* zTUi3eojM<`imv}27f$_oeE3N7&c&+p9%cBn^;HiaCAY)*H6Qk6j%}qm$L4+0t|R!M zwIPxc5kc6VieYx{%IuhX~b=LC~oUiQ6h_Q%=PO%J2pwsyUhcBjK^ zEc{^nxLH{b_U*jCcH7{9;1|ID{tobEdH=Zj?%jm%o?D>c0_DSbuj6!j`Q)ED=IJ~` z8^_hLLttKYzXBX)d)fHu)M~1w)pIH#w%(2+RFfpd_vQ`K`ZTGPUEzStsSk`8 zTIpk>d6!rS6RGZ& z!mf5VcjYB|f@a=Tj%HLNcgDeMD-}5>A0s8BkV_xa+AQk_N@} zFxxObp6<yg~(>vg_;jFv<9h}>}`zE#&cCZ!)1j*YV)t7=^nzI-^X!eq8PalOjd#kb4 zT*=wy61Nr@s6`CsAa1AIqCa|hTBpt>oA1&;eOcxs4DP}<+}-~_Y{T{eM;WK94Uar$v2zf1#2cxb)3Mo9Kgt7d^Mgl znK^hdNZaA2f4axO&eQ{@CVdlCnv8H6PuNavaIJ%I6eFhPbtsa1p)e}gc81u=3&1_# z9!9y(V^2eb@Qlr42ggFHj7pPEd&%`aV~V%vRBX3emVHE%0HxkJ$F6Om?{kaydNTGT zy;-4XPD3itX@Wa)RlD$DKa{3#t4`i}kIQZ$<2| zJ`N-XDyvd<)Q&S$yMS~2EfnvUuOI&d$fVi} delta 786 zcmWlX$q^km2t*H4p1Wgk0tgUGIBW{Q3H%g%aU_%A@O4uaOTTXZ{`~v%&+m`ExpKG& zFNeV+WM>ogfWwx0VUnLgT;SIcJ$T&j>4(!&2n`qKskci-Qdv!r4T2h#j~?O+mZEdI z?PQ)(e8zr|FMg`|TPp4-cqKzm)zd=C#K_fx4N+<)=r;8p*d+!K$9nEWPCn&|N9<)E zAVocjQ51eV!}T(hWI9C@%8@G=rlAx3sjTc#>+r0PN<`rE(-Y_|ptBy3 zoHL(z6}$$@n+<3*i}mV_`*a^oFU^@-upwJ~srGwn$L@CqsM#?mDv{Usy$lRa=&jV9 zc9-)iu;P%xIaIQ@MbIT64gR^Cpgri}c3gQI7&y|&wXUaB*WI+H+*5+nK(JG^*EaJ> w_u-Rs=tP%+#K>$5ckD4YbHq~8DvT|RFO3=Sm^^GN^Y`y*F7f|<|MTm||H-V|UH||9 diff --git a/tests/repository_data/project/test-flat/test-flat.json.gz b/tests/repository_data/project/test-flat/test-flat.json.gz deleted file mode 100644 index 48fd264d67829d8820beeae0959be7738dfc67bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1173 zcmV;G1Zw*qiwFS5shwE@|D{#ijvF@&ec!Jz<~eO8>PF@}`qUx_D3Mwl^W7cYIdZ{swL?tVSnJ7zU ze5fI2?yUsxd2-Ma@-$U*iXtW2B)2*!SSaMPiAf#W)8OGFu~TTAhIor9m%wPnqZ!BE z<7hNFOQc+ASYCHl5vo*b*A~Z^ZBXi+w4)WWprbKY6814?;F59(RcK6+lq87{X%s8Z zZZV`rEjH4TREl+#R&p4%cS)*)YOJM_a?|FTM<3n1v8i;j(jz`%jM;im+AFG;F@UeE z?Q6&CM*UlyAM z%@9qEE?t0360JQ|>fJyTsQ|p9Wf~o%H}VYBr_B`@4PLXpRJv;Z^Hz`B&$_>TIP6Z_ zyJuH8Z#Zrhs<|loy2d3em*uAquVtQRaidbAEN@6jp=ii6T_bDPkZ2wiriXPjYSJ>G`bV*!tbOF3vBWZeBJmhljnt z4)_j+cXR)5jDJGtUN4QU=f@Xt9`&?+ckFL-xA*kx>D%e&0w+J*?O@xx`_)ya?vMWR zY6~mhKI~Uw#n*{H-CU<${M+O1;`R%HR~Ex{?ItYw0{{nSJmniR*d#l&6L8b}vT6Vh%-Jk1SeR^d}u4qX~s_I`hR+M=%%->~WpR`j2-TEod1 z6fYqdgY`L6W@CqW5nP)ha*!roAxOki3u}s0~% zh^Z7{{$#niCqs^Rtpyfs@N_QlWA;@0hz)6-XI2A@aDT6y5cs96(J>HIL>?eNfHq7* n34;nUJ;3$;4J*01lJdgGuYNef-!620x_SB=ojVBhl?VU;5G^}N diff --git a/tests/repository_data/repository/metadata.staged/1.root.json b/tests/repository_data/repository/metadata.staged/1.root.json index f6998b4bbbe971cfff8e14a77e8329374980200f..79e296739fe947d388b9dc25176ae772fda6074b 100644 GIT binary patch delta 790 zcmWlXyA5td41@zDBwDyl;P-mV@oNjX4g4t~5>*h>1|bFE|3oVt%bxjW{`>Lwk3WBY zqCuDfbxI6Lu|;pE5RN=jsW|Z@i9P7}*%f`#EDG&Cml!04 zh1Clg5$f%rP*G5cP=Dq^V(>Jbijv|wNMU)86y~|Er@%ycR7v<`T!mA+90Dii+<=<` zA$=0erU)BcWcJ{xLg{{SzIHeg<{Y)roK(lvh)mnjkaeatCe7cAs#P-!0=SE>1&J0;-v@r2clFMEeDWGZy}O_s zSksMF;YCnOIk&uqxFU`$D~qFJ80g*jIu){-jL>FlG`jmZH+9A8x)_$|g_rVhCqlvP z6oMk>^Nx>Ey|J5kB3IoFdGBSTYrU#%04+A_t;jlmayN4hEG$dNlk^DAw*g4zWkMmm z3ibQ1;W{F(_{BzXB;vl1jM;)c%<{kwZFIhtXwN>=U|!PaZTwm>>Lw!jmjDtOJ0NB&EQspp2G>51 z@A#kh|Goe7<-t|b+h{$~k6n=Zh6+3j=~2YWY&*e14kXp`1>Gq($Xbq5k5X9j!i2lV zjnRXTlrKx_WpbBz8PNh?F-J3@NcM%DWZAN0?;RVa#on1VG_;{F>?La5EWhJ1BJoCQRs3$1`|cuPx@Q z31fuT{XkeF?lsldxmKhDkId_u-JQWT;FecvK#wS=si#V$C1lTN+vygZ&MW5IH*u36 znMv=0=-P+sh#{+??lTa>#3t$J4gWDo&NsX2g@tdG+aV?m(niaUuyHu`h=pkx| zN6~nGhKok*0#pOrz9#0{N7z(721}h>(dlw)1I4$Hgo}QjR{Qf-OAOHRP I-5+2755lkK`~Uy| diff --git a/tests/repository_data/repository/metadata.staged/1.root.json.gz b/tests/repository_data/repository/metadata.staged/1.root.json.gz deleted file mode 100644 index 5d5913af0a2c46f2bbdb434d881bdd4061adacdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1690 zcmV;L24(pliwFqgkDOTm12HagZ*O!iYIARH0L@m{ZX3xGeb-kIe3cD#4hHst98pvv zMNxs0uMDF@HS;jcD3A;P`_@RZ*1Oo?3-97yVhE7kJrz#Xsnb92)au1}n7i_R4MqJ! z?LRxU+Ryl{)u*r-M_j23&{{_zk!hK1WJVejqjgjf6@nH9q%g?>V_s=1y$+ry#gjFJ z%M^V5-LpM(Q(5BxGVzoQp=d+^m0D^rK%~&l8x97I5CEYF30?zOVr)`OIpZnlq?J=# zt7Hk+7UOb~o2U&VjxcMJ{M0R-iLZec(od7cR0SoU}rEaEuA!MZlvm5@1qUq9SuKNgD&gcwz+fm-)J1%WVnvd*LQ5+ZNeHK-)M)BBZU!%P2nq<* zjyUB7Mk$n$+-dCtf&wOrkfN6s6k%8&sj;6dAyV@yaBg&P8uw*lhF~I|1w`0shoC^B z5+QPgIG0$89MeQltW}I^hQL$Gv`9V%320L|6A0psEddpB$y>yl8>XW~P9R@s;4xtl z2*qlHPoCR4lHtov?bEwg=0U}=igESNceei?bGYgycicHnZc>ikXb(DM_xnlGOSyZE8Q%q^$n@@6)?C6L0VouKw%lgPXlM zs@0eGel`x(srS{V*=iqkYrU)H=}}fYY27|A-sPR6qvm4L=r)Jb)o40y+egxDoVN}d zjkBzAYZ}%5czA-pTMg2l^cL6a$%Tb%wOyQ>>ptA&y=g|mk(!p{)^OEJhpmf)?dEAS z$%G}@{f657{;3y^??0xl5}iz##o4sKJ7DvbSau{G-{nv9*p^R|hwfRkKRuR@S6MJ= zKbw`EtIOtWRoab&(<1GOz1E_6wY$y4#ej}`SG&9OtQeP@yF8tr>nnA7mh;wawpmXP zB^`a-iw`H6SlG+nZRh%_3*ne&r*uWwITiAFwwW|9?>qb^t_pXT=kfAzadXk{&F9-; zbC1T;y&%pfojhASu1^L;%@0mjw%@pIAGzZ}>g_0u^mxJkvyfSp7`{m@cq?=;u2RF?le|CMBZ>?zG z6vNH7(cNU1cGaI8-t6yh*?fAs+O0tY)jJUna z`$9j$P27jj>pl%O7(hh;cz}!j<$IgWxQ#RdfiEC z+~v-&P50o|-243O>iYOBk^H7T(lG z`~G@q+%K;!T7(hIzxHiWxcAGVc>mh)J8$Re5~oB=#w9}ySRBAOl!;a%;0V)Rpww8& zoFkEH>yc}Q3!Ho!Rg4p+P5igWhKeI4wckNFhyg{FGe>j`zKz-#B0B0=MAfgNL&tUr+!8c$ji88??bry}Ix_C|nN+ji|a>1jdpg=?rIFc;} zp%5&cKnP1ciU6_ve-9R3X_)a*Km-YaYonaEsHKrgk+`iUEhENIyybwhLHkOnB&xU4 zk{Bxg3$To%L7;fz4M9>FAy~t_vzC$|Q^anv)PY3InDjQJ#AGDOCsbEj-Ac^=0az@A zq#U+8vnD0MeR3p3#jQ~W?;XGi-mDNM1TYay5-&DjjZ}b4@kx9aSUayLPaTi&@2H`b`PH5%fO`@OzU+MY1@*gU{!|SB06MTn^8f$< diff --git a/tests/repository_data/repository/metadata.staged/role1.json.gz b/tests/repository_data/repository/metadata.staged/role1.json.gz deleted file mode 100644 index 4b9ff54595ccf99b4f7cc0808c48bed080750b1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 618 zcmV-w0+szAiwFSXkDOTo|E*KYZrd;ry!$H*ozs?FzVjVDwFrXca%l-sY{OE51cCp( ztB38R*H(}KQKWWfW@kP&+h*u?dmLX*JT&*)-<$3BL!NE(#P3~^FAYTnP*HQri87dk zJ{u1?ms&A-o7ihCK-s5MfNdsQOAW~=RO~G_cXK^yGgYg>hFS8e93)B z^JrucVA;8f0A4wdBBwT7HD^lA;e<`%b1=!RduHqbVZ0EMub0eRgJ4r{kpUhjaANab}N@ChW zKlw-Bh&^mpat*&7yCqZ&D5Jh9E%#5Q?&tg0Vy}zWF4p={yPnPW@ol^rZ1MvSpKP+a zKniQCB~Yq56QVAf(AgZ(DU?Z4mMylHKx0Z#hKdoDLqq~n3S#v6N_{obG^^?|qiF4w z)tO3xWP+ApR?fvn2gy@$wgzJ(%NtsWs3VnvOJ2po)&~qoinEi1o1(x%kw_Xc%5lsx zu>#gvL>sHMHma%}S7d=NabHcc0Bd^Q@5WYeLENkoFY3PXX^>DZ;-5F?Kil`@YRUuv E06!NjMgRZ+ diff --git a/tests/repository_data/repository/metadata.staged/role2.json.gz b/tests/repository_data/repository/metadata.staged/role2.json.gz deleted file mode 100644 index 6be24b7870f8b4bb48397fd371bd7e61cac2c3d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmV+)0pR{0iwFSYkDOTo|20rcYQsPb-TM?~)+x;2qnx9wmQW;(#+ZgA*luYEzI(@Z z0@6Z4dcQ~0s%hviIRA_?sbl-uwC$sItG?wv$)y9QQA_lw4jW#jSt%W#ZqaPRvO62E=RLdAioJcw-)-0fRaQIw lrcJGPt&dxM?9eZs7n1swajHahVVWv(`3FE~jtrgw000)?i^2c^ diff --git a/tests/repository_data/repository/metadata.staged/root.json b/tests/repository_data/repository/metadata.staged/root.json index f6998b4bbbe971cfff8e14a77e8329374980200f..79e296739fe947d388b9dc25176ae772fda6074b 100644 GIT binary patch delta 790 zcmWlXyA5td41@zDBwDyl;P-mV@oNjX4g4t~5>*h>1|bFE|3oVt%bxjW{`>Lwk3WBY zqCuDfbxI6Lu|;pE5RN=jsW|Z@i9P7}*%f`#EDG&Cml!04 zh1Clg5$f%rP*G5cP=Dq^V(>Jbijv|wNMU)86y~|Er@%ycR7v<`T!mA+90Dii+<=<` zA$=0erU)BcWcJ{xLg{{SzIHeg<{Y)roK(lvh)mnjkaeatCe7cAs#P-!0=SE>1&J0;-v@r2clFMEeDWGZy}O_s zSksMF;YCnOIk&uqxFU`$D~qFJ80g*jIu){-jL>FlG`jmZH+9A8x)_$|g_rVhCqlvP z6oMk>^Nx>Ey|J5kB3IoFdGBSTYrU#%04+A_t;jlmayN4hEG$dNlk^DAw*g4zWkMmm z3ibQ1;W{F(_{BzXB;vl1jM;)c%<{kwZFIhtXwN>=U|!PaZTwm>>Lw!jmjDtOJ0NB&EQspp2G>51 z@A#kh|Goe7<-t|b+h{$~k6n=Zh6+3j=~2YWY&*e14kXp`1>Gq($Xbq5k5X9j!i2lV zjnRXTlrKx_WpbBz8PNh?F-J3@NcM%DWZAN0?;RVa#on1VG_;{F>?La5EWhJ1BJoCQRs3$1`|cuPx@Q z31fuT{XkeF?lsldxmKhDkId_u-JQWT;FecvK#wS=si#V$C1lTN+vygZ&MW5IH*u36 znMv=0=-P+sh#{+??lTa>#3t$J4gWDo&NsX2g@tdG+aV?m(niaUuyHu`h=pkx| zN6~nGhKok*0#pOrz9#0{N7z(721}h>(dlw)1I4$Hgo}QjR{Qf-OAOHRP I-5+2755lkK`~Uy| diff --git a/tests/repository_data/repository/metadata.staged/snapshot.json.gz b/tests/repository_data/repository/metadata.staged/snapshot.json.gz deleted file mode 100644 index b482985be0979a897137f82e06a42adfb0f883cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmV-10nYv(iwFSYkDOTo|BaB%PQx$|gztF@%jbe@XE(O{9GpN1t-b3Kewr!?h^orF zlcWWS6P4DN*-x`GK2=H&?QT!wM=yiks)tIc)BKcvm1E1ZqA?P12~>g&5`{e_F}{Ip z68HoTOhiXy*!q|-`A|cX!5hl8aXzr#tbX&E#mzz?pMnW4Wfm02nJ^{Cv5oL8+EnkQB{5RT}+T0jB&z&*bb?(p5yNq=4 zQM&Km#NNIP-Tp^X`cwL$T?M-c)8?0SSCZX$6*yAAlX3WmtuFlE#Z*n-VWGLf5dr`J DW1W?8 diff --git a/tests/repository_data/repository/metadata.staged/targets.json.gz b/tests/repository_data/repository/metadata.staged/targets.json.gz deleted file mode 100644 index 0f54614b8db1ec7b44b88f7497b5db7253ec9c06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 815 zcmV+~1JL{*iwFSYkDOTo|D{w-kK;BBz2{d1K2KXxq&~R6qo)>w0VPqBpqV6yJ&Ro| z=D$~VJekR&?WKl&utbsXJw5WrW;=}g=c7)q7aNB!+dntk?T`L#hrjImzV?+Nc#P;g zs%UFoQzm56gv1F;hS-8ZHMWcrOAIklY{o2@BMAr%4@GtPxuZBYmmEU?}(t(rgWblg4Z;rVpgPrH}* zTUi3eojM<`imv}27f$_oeE3N7&c&+p9%cBn^;HiaCAY)*H6Qk6j%}qm$L4+0t|R!M zwIPxc5kc6VieYx{%IuhX~b=LC~oUiQ6h_Q%=PO%J2pwsyUhcBjK^ zEc{^nxLH{b_U*jCcH7{9;1|ID{tobEdH=Zj?%jm%o?D>c0_DSbuj6!j`Q)ED=IJ~` z8^_hLLttKYzXBX)d)fHu)M~1w)pIH#w%(2+RFfpd_vQ`K`ZTGPUEzStsSk`8 zTIpk>d6!rS6RGZ& z!mf5VcjYB|f@a=Tj%HLNcgDeMD-}5>A0s8BkV_xa+AQk_N@} zFxxObp6<yg~(>vg_;jFv<9h}>}`zE#&cCZ!)1j*YV)t7=^nzI-^X!eq8PalOjd#kb4 zT*=wy61Nr@s6`CsAa1AIqCa|hTBpt>oA1&;eOcxs4DP}<+}-~_Y{T{eM;W*h>1|bFE|3oVt%bxjW{`>Lwk3WBY zqCuDfbxI6Lu|;pE5RN=jsW|Z@i9P7}*%f`#EDG&Cml!04 zh1Clg5$f%rP*G5cP=Dq^V(>Jbijv|wNMU)86y~|Er@%ycR7v<`T!mA+90Dii+<=<` zA$=0erU)BcWcJ{xLg{{SzIHeg<{Y)roK(lvh)mnjkaeatCe7cAs#P-!0=SE>1&J0;-v@r2clFMEeDWGZy}O_s zSksMF;YCnOIk&uqxFU`$D~qFJ80g*jIu){-jL>FlG`jmZH+9A8x)_$|g_rVhCqlvP z6oMk>^Nx>Ey|J5kB3IoFdGBSTYrU#%04+A_t;jlmayN4hEG$dNlk^DAw*g4zWkMmm z3ibQ1;W{F(_{BzXB;vl1jM;)c%<{kwZFIhtXwN>=U|!PaZTwm>>Lw!jmjDtOJ0NB&EQspp2G>51 z@A#kh|Goe7<-t|b+h{$~k6n=Zh6+3j=~2YWY&*e14kXp`1>Gq($Xbq5k5X9j!i2lV zjnRXTlrKx_WpbBz8PNh?F-J3@NcM%DWZAN0?;RVa#on1VG_;{F>?La5EWhJ1BJoCQRs3$1`|cuPx@Q z31fuT{XkeF?lsldxmKhDkId_u-JQWT;FecvK#wS=si#V$C1lTN+vygZ&MW5IH*u36 znMv=0=-P+sh#{+??lTa>#3t$J4gWDo&NsX2g@tdG+aV?m(niaUuyHu`h=pkx| zN6~nGhKok*0#pOrz9#0{N7z(721}h>(dlw)1I4$Hgo}QjR{Qf-OAOHRP I-5+2755lkK`~Uy| diff --git a/tests/repository_data/repository/metadata/1.root.json.gz b/tests/repository_data/repository/metadata/1.root.json.gz deleted file mode 100644 index 5d5913af0a2c46f2bbdb434d881bdd4061adacdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1690 zcmV;L24(pliwFqgkDOTm12HagZ*O!iYIARH0L@m{ZX3xGeb-kIe3cD#4hHst98pvv zMNxs0uMDF@HS;jcD3A;P`_@RZ*1Oo?3-97yVhE7kJrz#Xsnb92)au1}n7i_R4MqJ! z?LRxU+Ryl{)u*r-M_j23&{{_zk!hK1WJVejqjgjf6@nH9q%g?>V_s=1y$+ry#gjFJ z%M^V5-LpM(Q(5BxGVzoQp=d+^m0D^rK%~&l8x97I5CEYF30?zOVr)`OIpZnlq?J=# zt7Hk+7UOb~o2U&VjxcMJ{M0R-iLZec(od7cR0SoU}rEaEuA!MZlvm5@1qUq9SuKNgD&gcwz+fm-)J1%WVnvd*LQ5+ZNeHK-)M)BBZU!%P2nq<* zjyUB7Mk$n$+-dCtf&wOrkfN6s6k%8&sj;6dAyV@yaBg&P8uw*lhF~I|1w`0shoC^B z5+QPgIG0$89MeQltW}I^hQL$Gv`9V%320L|6A0psEddpB$y>yl8>XW~P9R@s;4xtl z2*qlHPoCR4lHtov?bEwg=0U}=igESNceei?bGYgycicHnZc>ikXb(DM_xnlGOSyZE8Q%q^$n@@6)?C6L0VouKw%lgPXlM zs@0eGel`x(srS{V*=iqkYrU)H=}}fYY27|A-sPR6qvm4L=r)Jb)o40y+egxDoVN}d zjkBzAYZ}%5czA-pTMg2l^cL6a$%Tb%wOyQ>>ptA&y=g|mk(!p{)^OEJhpmf)?dEAS z$%G}@{f657{;3y^??0xl5}iz##o4sKJ7DvbSau{G-{nv9*p^R|hwfRkKRuR@S6MJ= zKbw`EtIOtWRoab&(<1GOz1E_6wY$y4#ej}`SG&9OtQeP@yF8tr>nnA7mh;wawpmXP zB^`a-iw`H6SlG+nZRh%_3*ne&r*uWwITiAFwwW|9?>qb^t_pXT=kfAzadXk{&F9-; zbC1T;y&%pfojhASu1^L;%@0mjw%@pIAGzZ}>g_0u^mxJkvyfSp7`{m@cq?=;u2RF?le|CMBZ>?zG z6vNH7(cNU1cGaI8-t6yh*?fAs+O0tY)jJUna z`$9j$P27jj>pl%O7(hh;cz}!j<$IgWxQ#RdfiEC z+~v-&P50o|-243O>iYOBk^H7T(lG z`~G@q+%K;!T7(hIzxHiWxcAGVc>mh)J8$Re5~oB=#w9}ySRBAOl!;a%;0V)Rpww8& zoFkEH>yc}Q3!Ho!Rg4p+P5igWhKeI4wckNFhyg{FGe>j`zKz-#B0B0=MAfgNL&tUr+!8c$ji88??bry}Ix_C|nN+ji|a>1jdpg=?rIFc;} zp%5&cKnP1ciU6_ve-9R3X_)a*Km-YaYonaEsHKrgk+`iUEhENIyybwhLHkOnB&xU4 zk{Bxg3$To%L7;fz4M9>FAy~t_vzC$|Q^anv)PY3InDjQJ#AGDOCsbEj-Ac^=0az@A zq#U+8vnD0MeR3p3#jQ~W?;XGi-mDNM1TYay5-&DjjZ}b4@kx9aSUayLPaTi&@2H`b`PH5%fO`@OzU+MY1@*gU{!|SB06MTn^8f$< diff --git a/tests/repository_data/repository/metadata/role1.json.gz b/tests/repository_data/repository/metadata/role1.json.gz deleted file mode 100644 index 4b9ff54595ccf99b4f7cc0808c48bed080750b1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 618 zcmV-w0+szAiwFSXkDOTo|E*KYZrd;ry!$H*ozs?FzVjVDwFrXca%l-sY{OE51cCp( ztB38R*H(}KQKWWfW@kP&+h*u?dmLX*JT&*)-<$3BL!NE(#P3~^FAYTnP*HQri87dk zJ{u1?ms&A-o7ihCK-s5MfNdsQOAW~=RO~G_cXK^yGgYg>hFS8e93)B z^JrucVA;8f0A4wdBBwT7HD^lA;e<`%b1=!RduHqbVZ0EMub0eRgJ4r{kpUhjaANab}N@ChW zKlw-Bh&^mpat*&7yCqZ&D5Jh9E%#5Q?&tg0Vy}zWF4p={yPnPW@ol^rZ1MvSpKP+a zKniQCB~Yq56QVAf(AgZ(DU?Z4mMylHKx0Z#hKdoDLqq~n3S#v6N_{obG^^?|qiF4w z)tO3xWP+ApR?fvn2gy@$wgzJ(%NtsWs3VnvOJ2po)&~qoinEi1o1(x%kw_Xc%5lsx zu>#gvL>sHMHma%}S7d=NabHcc0Bd^Q@5WYeLENkoFY3PXX^>DZ;-5F?Kil`@YRUuv E06!NjMgRZ+ diff --git a/tests/repository_data/repository/metadata/role2.json.gz b/tests/repository_data/repository/metadata/role2.json.gz deleted file mode 100644 index 6be24b7870f8b4bb48397fd371bd7e61cac2c3d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 287 zcmV+)0pR{0iwFSYkDOTo|20rcYQsPb-TM?~)+x;2qnx9wmQW;(#+ZgA*luYEzI(@Z z0@6Z4dcQ~0s%hviIRA_?sbl-uwC$sItG?wv$)y9QQA_lw4jW#jSt%W#ZqaPRvO62E=RLdAioJcw-)-0fRaQIw lrcJGPt&dxM?9eZs7n1swajHahVVWv(`3FE~jtrgw000)?i^2c^ diff --git a/tests/repository_data/repository/metadata/root.json b/tests/repository_data/repository/metadata/root.json index f6998b4bbbe971cfff8e14a77e8329374980200f..79e296739fe947d388b9dc25176ae772fda6074b 100644 GIT binary patch delta 790 zcmWlXyA5td41@zDBwDyl;P-mV@oNjX4g4t~5>*h>1|bFE|3oVt%bxjW{`>Lwk3WBY zqCuDfbxI6Lu|;pE5RN=jsW|Z@i9P7}*%f`#EDG&Cml!04 zh1Clg5$f%rP*G5cP=Dq^V(>Jbijv|wNMU)86y~|Er@%ycR7v<`T!mA+90Dii+<=<` zA$=0erU)BcWcJ{xLg{{SzIHeg<{Y)roK(lvh)mnjkaeatCe7cAs#P-!0=SE>1&J0;-v@r2clFMEeDWGZy}O_s zSksMF;YCnOIk&uqxFU`$D~qFJ80g*jIu){-jL>FlG`jmZH+9A8x)_$|g_rVhCqlvP z6oMk>^Nx>Ey|J5kB3IoFdGBSTYrU#%04+A_t;jlmayN4hEG$dNlk^DAw*g4zWkMmm z3ibQ1;W{F(_{BzXB;vl1jM;)c%<{kwZFIhtXwN>=U|!PaZTwm>>Lw!jmjDtOJ0NB&EQspp2G>51 z@A#kh|Goe7<-t|b+h{$~k6n=Zh6+3j=~2YWY&*e14kXp`1>Gq($Xbq5k5X9j!i2lV zjnRXTlrKx_WpbBz8PNh?F-J3@NcM%DWZAN0?;RVa#on1VG_;{F>?La5EWhJ1BJoCQRs3$1`|cuPx@Q z31fuT{XkeF?lsldxmKhDkId_u-JQWT;FecvK#wS=si#V$C1lTN+vygZ&MW5IH*u36 znMv=0=-P+sh#{+??lTa>#3t$J4gWDo&NsX2g@tdG+aV?m(niaUuyHu`h=pkx| zN6~nGhKok*0#pOrz9#0{N7z(721}h>(dlw)1I4$Hgo}QjR{Qf-OAOHRP I-5+2755lkK`~Uy| diff --git a/tests/repository_data/repository/metadata/snapshot.json.gz b/tests/repository_data/repository/metadata/snapshot.json.gz deleted file mode 100644 index b482985be0979a897137f82e06a42adfb0f883cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 305 zcmV-10nYv(iwFSYkDOTo|BaB%PQx$|gztF@%jbe@XE(O{9GpN1t-b3Kewr!?h^orF zlcWWS6P4DN*-x`GK2=H&?QT!wM=yiks)tIc)BKcvm1E1ZqA?P12~>g&5`{e_F}{Ip z68HoTOhiXy*!q|-`A|cX!5hl8aXzr#tbX&E#mzz?pMnW4Wfm02nJ^{Cv5oL8+EnkQB{5RT}+T0jB&z&*bb?(p5yNq=4 zQM&Km#NNIP-Tp^X`cwL$T?M-c)8?0SSCZX$6*yAAlX3WmtuFlE#Z*n-VWGLf5dr`J DW1W?8 diff --git a/tests/repository_data/repository/metadata/targets.json.gz b/tests/repository_data/repository/metadata/targets.json.gz deleted file mode 100644 index 0f54614b8db1ec7b44b88f7497b5db7253ec9c06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 815 zcmV+~1JL{*iwFSYkDOTo|D{w-kK;BBz2{d1K2KXxq&~R6qo)>w0VPqBpqV6yJ&Ro| z=D$~VJekR&?WKl&utbsXJw5WrW;=}g=c7)q7aNB!+dntk?T`L#hrjImzV?+Nc#P;g zs%UFoQzm56gv1F;hS-8ZHMWcrOAIklY{o2@BMAr%4@GtPxuZBYmmEU?}(t(rgWblg4Z;rVpgPrH}* zTUi3eojM<`imv}27f$_oeE3N7&c&+p9%cBn^;HiaCAY)*H6Qk6j%}qm$L4+0t|R!M zwIPxc5kc6VieYx{%IuhX~b=LC~oUiQ6h_Q%=PO%J2pwsyUhcBjK^ zEc{^nxLH{b_U*jCcH7{9;1|ID{tobEdH=Zj?%jm%o?D>c0_DSbuj6!j`Q)ED=IJ~` z8^_hLLttKYzXBX)d)fHu)M~1w)pIH#w%(2+RFfpd_vQ`K`ZTGPUEzStsSk`8 zTIpk>d6!rS6RGZ& z!mf5VcjYB|f@a=Tj%HLNcgDeMD-}5>A0s8BkV_xa+AQk_N@} zFxxObp6<yg~(>vg_;jFv<9h}>}`zE#&cCZ!)1j*YV)t7=^nzI-^X!eq8PalOjd#kb4 zT*=wy61Nr@s6`CsAa1AIqCa|hTBpt>oA1&;eOcxs4DP}<+}-~_Y{T{eM;W Date: Mon, 28 Aug 2017 10:20:46 -0400 Subject: [PATCH 17/24] Do not mention compression in README.md --- tuf/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tuf/README.md b/tuf/README.md index adb740b6..2185253e 100644 --- a/tuf/README.md +++ b/tuf/README.md @@ -202,8 +202,8 @@ top-level roles, including itself. # A role's verification key(s) (to be more precise, the verification key's # keyid) may be queried. Other attributes include: signing_keys, version, -# signatures, expiration, threshold, delegations (attribute available only to a -# Targets role), and compressions. +# signatures, expiration, threshold, and delegations (attribute available only +# to a Targets role). >>> repository.root.keys ['b23514431a53676595922e955c2d547293da4a7917e3ca243a175e72bbf718df'] From d2f85ec2b41649e53499f2a5922f451e9b3f69a8 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Mon, 28 Aug 2017 11:16:43 -0400 Subject: [PATCH 18/24] Remove mention of compression from specification --- docs/tuf-spec.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docs/tuf-spec.md b/docs/tuf-spec.md index 046c6401..8bdb295f 100644 --- a/docs/tuf-spec.md +++ b/docs/tuf-spec.md @@ -420,13 +420,6 @@ Version: **1.0 (Draft)** Signed by the mirrors role's keys. Lists information about available mirrors and the content available from each mirror. - An implementation of the framework may optionally choose to make available - any metadata files in compressed (e.g. gzip'd) format. In doing so, the - filename of the compressed file should be the same as the original with the - addition of the file name extension for the compression type (e.g. - snapshot.json.gz). The original (uncompressed) file should always be made - available, as well. - + **3.1.2.1 Metadata files for targets delegation** When the targets role delegates trust to other roles, each delegated role @@ -541,7 +534,6 @@ Version: **1.0 (Draft)** The "signed" portion of root.json is as follows: { "_type" : "root", - "compression_algorithms": [ COMPRESSION_ALGORITHM, ... ], "consistent_snapshot": CONSISTENT_SNAPSHOT, "version" : VERSION, "expires" : EXPIRES, @@ -555,11 +547,6 @@ Version: **1.0 (Draft)** , ... } } - COMPRESSION_ALGORITHM specifies one of the compression algorithms supported - by the repository. Metadata files available on the repository may - optionally be compressed with this algorithm. Compressed versions of - metadata are not listed in snapshot.json. - CONSISTENT_SNAPSHOT is a boolean indicating whether the repository supports consistent snapshots. Section 7 goes into more detail on the consequences of enabling this setting on a repository. From d4f6362dcf01b4e2cbbe974eed13fe35f64d6f42 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Mon, 28 Aug 2017 15:12:57 -0400 Subject: [PATCH 19/24] Add metadata that contains 'spec_version' --- .../test_repository/metadata/current/1.root.json | Bin 0 -> 3394 bytes .../test_repository/metadata/current/role1.json | Bin 0 -> 1251 bytes .../test_repository/metadata/current/role2.json | Bin 0 -> 439 bytes .../test_repository/metadata/current/root.json | Bin 0 -> 3394 bytes .../metadata/current/snapshot.json | Bin 0 -> 554 bytes .../metadata/current/targets.json | Bin 0 -> 1624 bytes .../metadata/current/timestamp.json | Bin 0 -> 555 bytes .../metadata/previous/1.root.json | Bin 0 -> 3394 bytes .../test_repository/metadata/previous/role1.json | Bin 0 -> 1251 bytes .../test_repository/metadata/previous/role2.json | Bin 0 -> 439 bytes .../test_repository/metadata/previous/root.json | Bin 0 -> 3394 bytes .../metadata/previous/snapshot.json | Bin 0 -> 554 bytes .../metadata/previous/targets.json | Bin 0 -> 1624 bytes .../metadata/previous/timestamp.json | Bin 0 -> 555 bytes .../repository/metadata.staged/1.root.json | Bin 0 -> 3394 bytes .../repository/metadata.staged/role1.json | Bin 0 -> 1251 bytes .../repository/metadata.staged/role2.json | Bin 0 -> 439 bytes .../repository/metadata.staged/root.json | Bin 0 -> 3394 bytes .../repository/metadata.staged/snapshot.json | Bin 0 -> 554 bytes .../repository/metadata.staged/targets.json | Bin 0 -> 1624 bytes .../repository/metadata.staged/timestamp.json | Bin 0 -> 555 bytes .../repository/metadata/1.root.json | Bin 0 -> 3394 bytes .../repository/metadata/role1.json | Bin 0 -> 1251 bytes .../repository/metadata/role2.json | Bin 0 -> 439 bytes .../repository/metadata/root.json | Bin 0 -> 3394 bytes .../repository/metadata/snapshot.json | Bin 0 -> 554 bytes .../repository/metadata/targets.json | Bin 0 -> 1624 bytes .../repository/metadata/timestamp.json | Bin 0 -> 555 bytes .../repository_data/repository/targets/file1.txt | 1 + .../repository_data/repository/targets/file2.txt | 1 + .../repository_data/repository/targets/file3.txt | 1 + 31 files changed, 3 insertions(+) create mode 100644 tests/repository_data/client/test_repository/metadata/current/1.root.json create mode 100644 tests/repository_data/client/test_repository/metadata/current/role1.json create mode 100644 tests/repository_data/client/test_repository/metadata/current/role2.json create mode 100644 tests/repository_data/client/test_repository/metadata/current/root.json create mode 100644 tests/repository_data/client/test_repository/metadata/current/snapshot.json create mode 100644 tests/repository_data/client/test_repository/metadata/current/targets.json create mode 100644 tests/repository_data/client/test_repository/metadata/current/timestamp.json create mode 100644 tests/repository_data/client/test_repository/metadata/previous/1.root.json create mode 100644 tests/repository_data/client/test_repository/metadata/previous/role1.json create mode 100644 tests/repository_data/client/test_repository/metadata/previous/role2.json create mode 100644 tests/repository_data/client/test_repository/metadata/previous/root.json create mode 100644 tests/repository_data/client/test_repository/metadata/previous/snapshot.json create mode 100644 tests/repository_data/client/test_repository/metadata/previous/targets.json create mode 100644 tests/repository_data/client/test_repository/metadata/previous/timestamp.json create mode 100644 tests/repository_data/repository/metadata.staged/1.root.json create mode 100644 tests/repository_data/repository/metadata.staged/role1.json create mode 100644 tests/repository_data/repository/metadata.staged/role2.json create mode 100644 tests/repository_data/repository/metadata.staged/root.json create mode 100644 tests/repository_data/repository/metadata.staged/snapshot.json create mode 100644 tests/repository_data/repository/metadata.staged/targets.json create mode 100644 tests/repository_data/repository/metadata.staged/timestamp.json create mode 100644 tests/repository_data/repository/metadata/1.root.json create mode 100644 tests/repository_data/repository/metadata/role1.json create mode 100644 tests/repository_data/repository/metadata/role2.json create mode 100644 tests/repository_data/repository/metadata/root.json create mode 100644 tests/repository_data/repository/metadata/snapshot.json create mode 100644 tests/repository_data/repository/metadata/targets.json create mode 100644 tests/repository_data/repository/metadata/timestamp.json create mode 100644 tests/repository_data/repository/targets/file1.txt create mode 100644 tests/repository_data/repository/targets/file2.txt create mode 100644 tests/repository_data/repository/targets/file3.txt diff --git a/tests/repository_data/client/test_repository/metadata/current/1.root.json b/tests/repository_data/client/test_repository/metadata/current/1.root.json new file mode 100644 index 0000000000000000000000000000000000000000..ccce5381b64b408a996cb3e63b4a3edd99712f02 GIT binary patch literal 3394 zcmd5;*={385`3SpAo!{stL|ffeIQ#Db&;Z|gVL-Fp|0fJJi2vI#{BzclNwt#;N4kh z0h{2}RbAOpSs4-e%coks7!Pw-KCV+y|5E$cr&{e7{M72xv>8Vnsf(nwj)_F3CD_P} zG$uyts3Ix^EliTafK7~frLFWjcn*q#HH1qDzW$GGJbX+QjSG<&x7J(3geHzC?_I)0 zQL^NviQqJNr(~qsI?c7`O3IM5g`^o1hJck+QpE`+UQ-d1k3uDPCAb}7|ogs))gCK#VB(3ux ztd!0hWmq(VP$1StFPJCE7^{O-F6iXBHUi;jjOP`nDJe}2#-~YoZn?s>jw@qmFv)7B zA|}EI#SjH>BW$z+L*YR3#5tvcjoc`k1mRW?FrXt~COnJWIZABsz;&ctScEJ%w=$^6 zT;vi{izz~Q&T$)sj4E-w&=83dQhOjkICs@aYKvRPlTsuRD-d#Yj0OeVnZc zS%jmAHqqb^3&coj6euqVT%lAOJyt?;f-2!D7@X&tMxPW%Kr~Ql2%<}MB*V8)wV#m`Tjr&TV-@4- z59MZ=DvGQZi*ievdRXMexF}OzJ`}lI79*VaQUf}XabouCK<4|ShbM z=5V?iO~-BfOqz|0)?uS@o;B`FqnaNNPw{`NLE4kv;$}U$v?*J?E-uVXKi%iOX-2}a znwI0%aMgpO*5%>r=4CUfzd~1uPA1IaeA?d|u=z?XJCcs?^Ot#S z%a_Sh_q^Gkp2+9xEEqV*W@YF4sySPgb|ceS0sCUVwP;@Ny=LNaK*zo7y}fx>jLXe^ z4i^{tTAiKeymgmt*3%2j(`hCa_NsT+xq0cPaKf`Qx+3g?3VAZyOqy4Z9ex{E zg}cx5cy+Y6z3lhq^VeZ>pT@KOATB1IJX<`kPX|QJ56@P%-?(cZyORNQ_DSZ~=O@dX zgK6Vx-U^t>xNM)?9l&6}=wCebR@+vc%9zq!v}t!UpC!_8}>yUDKXsy{ipJvew}^Xb`Y&mOb!Y1vx2R_cX8|B)Z5 z{+SysJNs8Jhp*4dh`al|FZ6S|jRz_8x-Wyxcre~{+LvYjuqU#iE!W|>(au|Q`fU1a zIGhibqt`q`dAMzldff>$?sI3@rh9m29({g(eRFaSB)@GBc`H8K@g2uwJ@ITWUl&se zyfN%F8;#aK@AGXjwYmp?tgl_+e%o3Z)^-@B`HriFD+>2{Srnh&3cjlF-F<97{=bneMJ6S+KR~z? z(NG;{j_4Q?=b(c|Rdr}_9smu8q3CmzS1q+jsHI${1o(qG99@WimbUK*-X%*(swtDy zSqv_nLD3Z4p*0J%Gfy-qY(bJh)ki0kEqPnpp!NxCe*bo8lImAcK7ZClWUlu#Lht z3peQ!!%j^qY!W^8OFxt>EUzsU(NbsI_I782TZ8?*k-c}W4}0YAOs*WELys1-ip}(0 zy}vW`Evh$1eGlZr`td_RO1B=SvU={H;rK8$e+QBM>W%I8S});v%TaDB0caLwGeI*hCz=C@h4 zEiv47Ehvk8*Y!Oft&UOE8>m)$=@6C4niR-F>#{6uX4sgFiee1nHU$DpL>V&xhTzg& z6G>c4n3Uvd6O;T192k{yDHyd^MoMxjCRmIv7i+55Ca~O*DWGkJ=xuZm3QLEQrwp8I z@KzTQn-)Zq literal 0 HcmV?d00001 diff --git a/tests/repository_data/client/test_repository/metadata/current/role2.json b/tests/repository_data/client/test_repository/metadata/current/role2.json new file mode 100644 index 0000000000000000000000000000000000000000..46e415a7892b9785f63f3e85e7015953804ffafa GIT binary patch literal 439 zcmYL_-D<-y42AFW6v5ZqkmdhA$F4R?k!_`fm9`|=SSfw?$qCy)zK|@=`E>4GujcW1 zrsZ?uS?&7wuJ7;idiBA#vC2f12#5n|PC1o~CXvs^W6pILD0!RMYpPhXPpKl?T;D6p_#VV4cXYHelC;FZ8Ux_&QE>*d^TY!|D;a=UUv zTxdG-GOygK@`;bMjF)qZ=P#PId2E+Wm(!NrzG=6a;_vIY1*#AXJcE{c1=y|iwn@)d bE{89kW)W|``USR+UjXsj8Vnsf(nwj)_F3CD_P} zG$uyts3Ix^EliTafK7~frLFWjcn*q#HH1qDzW$GGJbX+QjSG<&x7J(3geHzC?_I)0 zQL^NviQqJNr(~qsI?c7`O3IM5g`^o1hJck+QpE`+UQ-d1k3uDPCAb}7|ogs))gCK#VB(3ux ztd!0hWmq(VP$1StFPJCE7^{O-F6iXBHUi;jjOP`nDJe}2#-~YoZn?s>jw@qmFv)7B zA|}EI#SjH>BW$z+L*YR3#5tvcjoc`k1mRW?FrXt~COnJWIZABsz;&ctScEJ%w=$^6 zT;vi{izz~Q&T$)sj4E-w&=83dQhOjkICs@aYKvRPlTsuRD-d#Yj0OeVnZc zS%jmAHqqb^3&coj6euqVT%lAOJyt?;f-2!D7@X&tMxPW%Kr~Ql2%<}MB*V8)wV#m`Tjr&TV-@4- z59MZ=DvGQZi*ievdRXMexF}OzJ`}lI79*VaQUf}XabouCK<4|ShbM z=5V?iO~-BfOqz|0)?uS@o;B`FqnaNNPw{`NLE4kv;$}U$v?*J?E-uVXKi%iOX-2}a znwI0%aMgpO*5%>r=4CUfzd~1uPA1IaeA?d|u=z?XJCcs?^Ot#S z%a_Sh_q^Gkp2+9xEEqV*W@YF4sySPgb|ceS0sCUVwP;@Ny=LNaK*zo7y}fx>jLXe^ z4i^{tTAiKeymgmt*3%2j(`hCa_NsT+xq0cPaKf`Qx+3g?3VAZyOqy4Z9ex{E zg}cx5cy+Y6z3lhq^VeZ>pT@KOATB1IJX<`kPX|QJ56@P%-?(cZyORNQ_DSZ~=O@dX zgK6Vx-U^t>xNM)?9l&6}=wCebR@+vc%9zq!v}t!UpC!_8}>yUDKXsy{ipJvew}^Xb`Y&mOb!Y1vx2R_cX8|B)Z5 z{+SysJNs8Jhp*4dh`al|FZ6S|jRz_8x-Wyxcre~{+LvYjuqU#iE!W|>(au|Q`fU1a zIGhibqt`q`dAMzldff>$?sI3@rh9m29({g(eRFaSB)@GBc`H8K@g2uwJ@ITWUl&se zyfN%F8;#aK@AGXjwYmp?tgl_+e%o3Z)^-@B`HriFD+>2{Srnh&3cjlF-F<97{=bneMJ6S+KR~z? z(NG;{j_4Q?=b(c|Rdr}_9smu8q3CmzS1q+jsHI${1o(qG99@WimbUK*-X%*(swtDy zSqv_nLD3Z4p*0J%Gfy-qY(bJh)ki0kEqPnpp!NxCe*bo8lImAcK7ZClWUlu#Lht z3peQ!!%j^qY!W^8OFxt>EUzsU(NbsI_I782TZ8?*k-c}W4}0YAOs*WELys1-ip}(0 zy}vW`Evh$1eGlZr`td_RO1B=SvU={H;rK8$e+QW?RyKPOINUq4lKeaWvDZ+z}!-iXGLj-92>O3RL;APhLhsvKpH}q^;B{MB@l$t1t!zloSn1Z>@?}8PkAj zVyBcM>#+?kK&i vsb3eew6ScR6eZrM9Oj#ZGfhXH(?8l$LO~E||VCf2Hf2e zRaGq3@2AalJ?u_0zh3k@ecpV1+H8K?Z!>+@Ux#LIrWi1x3n(nT2g$`FdCBN0V=a(+ zRA@?CkW)=DWuLkdF_z>R*iU~f_3W5Y%@-8xwJ~y{^xTmH^-N}4-ISqLp(mWnEQ_bL97gR1>i}Nh8_~=S$ zy$eTTjVR645}BJ*DwTTci9HBtBw5R@ns4`V-EZZ%d$}Cu{qx!t>xm)Wiwp6l=>0k1 z!pWWnr*Vzetz5LZ5Rlg$nsw?ezZ=sjmehhDDcywM!|1h)^XJ6AI<7;(XP ze`S_@z0NPswr%mNDLQy;&ja&y6dWX{NOWU$Z`d?^w{&COb$8oX8%nM*^?;Sxx6IiE z=ma7miO1A(AOd(N&3nV;mzLcmnHFu`M{WN@C9=TMY*P{dTDHLMQ`A8#^0^=+vGF;TF1aZ+q0q^c!FnPGnxzVy z8wg{;K+)VCd_!hu3$@nVH2KOkf+gpjBfZ}Z?K@*mJ2eeKI(2KUp^!0p=fRm;=o*5Ezd5`ALh$Mtmm2Vl05dH?_b literal 0 HcmV?d00001 diff --git a/tests/repository_data/client/test_repository/metadata/previous/1.root.json b/tests/repository_data/client/test_repository/metadata/previous/1.root.json new file mode 100644 index 0000000000000000000000000000000000000000..ccce5381b64b408a996cb3e63b4a3edd99712f02 GIT binary patch literal 3394 zcmd5;*={385`3SpAo!{stL|ffeIQ#Db&;Z|gVL-Fp|0fJJi2vI#{BzclNwt#;N4kh z0h{2}RbAOpSs4-e%coks7!Pw-KCV+y|5E$cr&{e7{M72xv>8Vnsf(nwj)_F3CD_P} zG$uyts3Ix^EliTafK7~frLFWjcn*q#HH1qDzW$GGJbX+QjSG<&x7J(3geHzC?_I)0 zQL^NviQqJNr(~qsI?c7`O3IM5g`^o1hJck+QpE`+UQ-d1k3uDPCAb}7|ogs))gCK#VB(3ux ztd!0hWmq(VP$1StFPJCE7^{O-F6iXBHUi;jjOP`nDJe}2#-~YoZn?s>jw@qmFv)7B zA|}EI#SjH>BW$z+L*YR3#5tvcjoc`k1mRW?FrXt~COnJWIZABsz;&ctScEJ%w=$^6 zT;vi{izz~Q&T$)sj4E-w&=83dQhOjkICs@aYKvRPlTsuRD-d#Yj0OeVnZc zS%jmAHqqb^3&coj6euqVT%lAOJyt?;f-2!D7@X&tMxPW%Kr~Ql2%<}MB*V8)wV#m`Tjr&TV-@4- z59MZ=DvGQZi*ievdRXMexF}OzJ`}lI79*VaQUf}XabouCK<4|ShbM z=5V?iO~-BfOqz|0)?uS@o;B`FqnaNNPw{`NLE4kv;$}U$v?*J?E-uVXKi%iOX-2}a znwI0%aMgpO*5%>r=4CUfzd~1uPA1IaeA?d|u=z?XJCcs?^Ot#S z%a_Sh_q^Gkp2+9xEEqV*W@YF4sySPgb|ceS0sCUVwP;@Ny=LNaK*zo7y}fx>jLXe^ z4i^{tTAiKeymgmt*3%2j(`hCa_NsT+xq0cPaKf`Qx+3g?3VAZyOqy4Z9ex{E zg}cx5cy+Y6z3lhq^VeZ>pT@KOATB1IJX<`kPX|QJ56@P%-?(cZyORNQ_DSZ~=O@dX zgK6Vx-U^t>xNM)?9l&6}=wCebR@+vc%9zq!v}t!UpC!_8}>yUDKXsy{ipJvew}^Xb`Y&mOb!Y1vx2R_cX8|B)Z5 z{+SysJNs8Jhp*4dh`al|FZ6S|jRz_8x-Wyxcre~{+LvYjuqU#iE!W|>(au|Q`fU1a zIGhibqt`q`dAMzldff>$?sI3@rh9m29({g(eRFaSB)@GBc`H8K@g2uwJ@ITWUl&se zyfN%F8;#aK@AGXjwYmp?tgl_+e%o3Z)^-@B`HriFD+>2{Srnh&3cjlF-F<97{=bneMJ6S+KR~z? z(NG;{j_4Q?=b(c|Rdr}_9smu8q3CmzS1q+jsHI${1o(qG99@WimbUK*-X%*(swtDy zSqv_nLD3Z4p*0J%Gfy-qY(bJh)ki0kEqPnpp!NxCe*bo8lImAcK7ZClWUlu#Lht z3peQ!!%j^qY!W^8OFxt>EUzsU(NbsI_I782TZ8?*k-c}W4}0YAOs*WELys1-ip}(0 zy}vW`Evh$1eGlZr`td_RO1B=SvU={H;rK8$e+QBM>W%I8S});v%TaDB0caLwGeI*hCz=C@h4 zEiv47Ehvk8*Y!Oft&UOE8>m)$=@6C4niR-F>#{6uX4sgFiee1nHU$DpL>V&xhTzg& z6G>c4n3Uvd6O;T192k{yDHyd^MoMxjCRmIv7i+55Ca~O*DWGkJ=xuZm3QLEQrwp8I z@KzTQn-)Zq literal 0 HcmV?d00001 diff --git a/tests/repository_data/client/test_repository/metadata/previous/role2.json b/tests/repository_data/client/test_repository/metadata/previous/role2.json new file mode 100644 index 0000000000000000000000000000000000000000..46e415a7892b9785f63f3e85e7015953804ffafa GIT binary patch literal 439 zcmYL_-D<-y42AFW6v5ZqkmdhA$F4R?k!_`fm9`|=SSfw?$qCy)zK|@=`E>4GujcW1 zrsZ?uS?&7wuJ7;idiBA#vC2f12#5n|PC1o~CXvs^W6pILD0!RMYpPhXPpKl?T;D6p_#VV4cXYHelC;FZ8Ux_&QE>*d^TY!|D;a=UUv zTxdG-GOygK@`;bMjF)qZ=P#PId2E+Wm(!NrzG=6a;_vIY1*#AXJcE{c1=y|iwn@)d bE{89kW)W|``USR+UjXsj8Vnsf(nwj)_F3CD_P} zG$uyts3Ix^EliTafK7~frLFWjcn*q#HH1qDzW$GGJbX+QjSG<&x7J(3geHzC?_I)0 zQL^NviQqJNr(~qsI?c7`O3IM5g`^o1hJck+QpE`+UQ-d1k3uDPCAb}7|ogs))gCK#VB(3ux ztd!0hWmq(VP$1StFPJCE7^{O-F6iXBHUi;jjOP`nDJe}2#-~YoZn?s>jw@qmFv)7B zA|}EI#SjH>BW$z+L*YR3#5tvcjoc`k1mRW?FrXt~COnJWIZABsz;&ctScEJ%w=$^6 zT;vi{izz~Q&T$)sj4E-w&=83dQhOjkICs@aYKvRPlTsuRD-d#Yj0OeVnZc zS%jmAHqqb^3&coj6euqVT%lAOJyt?;f-2!D7@X&tMxPW%Kr~Ql2%<}MB*V8)wV#m`Tjr&TV-@4- z59MZ=DvGQZi*ievdRXMexF}OzJ`}lI79*VaQUf}XabouCK<4|ShbM z=5V?iO~-BfOqz|0)?uS@o;B`FqnaNNPw{`NLE4kv;$}U$v?*J?E-uVXKi%iOX-2}a znwI0%aMgpO*5%>r=4CUfzd~1uPA1IaeA?d|u=z?XJCcs?^Ot#S z%a_Sh_q^Gkp2+9xEEqV*W@YF4sySPgb|ceS0sCUVwP;@Ny=LNaK*zo7y}fx>jLXe^ z4i^{tTAiKeymgmt*3%2j(`hCa_NsT+xq0cPaKf`Qx+3g?3VAZyOqy4Z9ex{E zg}cx5cy+Y6z3lhq^VeZ>pT@KOATB1IJX<`kPX|QJ56@P%-?(cZyORNQ_DSZ~=O@dX zgK6Vx-U^t>xNM)?9l&6}=wCebR@+vc%9zq!v}t!UpC!_8}>yUDKXsy{ipJvew}^Xb`Y&mOb!Y1vx2R_cX8|B)Z5 z{+SysJNs8Jhp*4dh`al|FZ6S|jRz_8x-Wyxcre~{+LvYjuqU#iE!W|>(au|Q`fU1a zIGhibqt`q`dAMzldff>$?sI3@rh9m29({g(eRFaSB)@GBc`H8K@g2uwJ@ITWUl&se zyfN%F8;#aK@AGXjwYmp?tgl_+e%o3Z)^-@B`HriFD+>2{Srnh&3cjlF-F<97{=bneMJ6S+KR~z? z(NG;{j_4Q?=b(c|Rdr}_9smu8q3CmzS1q+jsHI${1o(qG99@WimbUK*-X%*(swtDy zSqv_nLD3Z4p*0J%Gfy-qY(bJh)ki0kEqPnpp!NxCe*bo8lImAcK7ZClWUlu#Lht z3peQ!!%j^qY!W^8OFxt>EUzsU(NbsI_I782TZ8?*k-c}W4}0YAOs*WELys1-ip}(0 zy}vW`Evh$1eGlZr`td_RO1B=SvU={H;rK8$e+QW?RyKPOINUq4lKeaWvDZ+z}!-iXGLj-92>O3RL;APhLhsvKpH}q^;B{MB@l$t1t!zloSn1Z>@?}8PkAj zVyBcM>#+?kK&i vsb3eew6ScR6eZrM9Oj#ZGfhXH(?8l$LO~E||VCf2Hf2e zRaGq3@2AalJ?u_0zh3k@ecpV1+H8K?Z!>+@Ux#LIrWi1x3n(nT2g$`FdCBN0V=a(+ zRA@?CkW)=DWuLkdF_z>R*iU~f_3W5Y%@-8xwJ~y{^xTmH^-N}4-ISqLp(mWnEQ_bL97gR1>i}Nh8_~=S$ zy$eTTjVR645}BJ*DwTTci9HBtBw5R@ns4`V-EZZ%d$}Cu{qx!t>xm)Wiwp6l=>0k1 z!pWWnr*Vzetz5LZ5Rlg$nsw?ezZ=sjmehhDDcywM!|1h)^XJ6AI<7;(XP ze`S_@z0NPswr%mNDLQy;&ja&y6dWX{NOWU$Z`d?^w{&COb$8oX8%nM*^?;Sxx6IiE z=ma7miO1A(AOd(N&3nV;mzLcmnHFu`M{WN@C9=TMY*P{dTDHLMQ`A8#^0^=+vGF;TF1aZ+q0q^c!FnPGnxzVy z8wg{;K+)VCd_!hu3$@nVH2KOkf+gpjBfZ}Z?K@*mJ2eeKI(2KUp^!0p=fRm;=o*5Ezd5`ALh$Mtmm2Vl05dH?_b literal 0 HcmV?d00001 diff --git a/tests/repository_data/repository/metadata.staged/1.root.json b/tests/repository_data/repository/metadata.staged/1.root.json new file mode 100644 index 0000000000000000000000000000000000000000..ccce5381b64b408a996cb3e63b4a3edd99712f02 GIT binary patch literal 3394 zcmd5;*={385`3SpAo!{stL|ffeIQ#Db&;Z|gVL-Fp|0fJJi2vI#{BzclNwt#;N4kh z0h{2}RbAOpSs4-e%coks7!Pw-KCV+y|5E$cr&{e7{M72xv>8Vnsf(nwj)_F3CD_P} zG$uyts3Ix^EliTafK7~frLFWjcn*q#HH1qDzW$GGJbX+QjSG<&x7J(3geHzC?_I)0 zQL^NviQqJNr(~qsI?c7`O3IM5g`^o1hJck+QpE`+UQ-d1k3uDPCAb}7|ogs))gCK#VB(3ux ztd!0hWmq(VP$1StFPJCE7^{O-F6iXBHUi;jjOP`nDJe}2#-~YoZn?s>jw@qmFv)7B zA|}EI#SjH>BW$z+L*YR3#5tvcjoc`k1mRW?FrXt~COnJWIZABsz;&ctScEJ%w=$^6 zT;vi{izz~Q&T$)sj4E-w&=83dQhOjkICs@aYKvRPlTsuRD-d#Yj0OeVnZc zS%jmAHqqb^3&coj6euqVT%lAOJyt?;f-2!D7@X&tMxPW%Kr~Ql2%<}MB*V8)wV#m`Tjr&TV-@4- z59MZ=DvGQZi*ievdRXMexF}OzJ`}lI79*VaQUf}XabouCK<4|ShbM z=5V?iO~-BfOqz|0)?uS@o;B`FqnaNNPw{`NLE4kv;$}U$v?*J?E-uVXKi%iOX-2}a znwI0%aMgpO*5%>r=4CUfzd~1uPA1IaeA?d|u=z?XJCcs?^Ot#S z%a_Sh_q^Gkp2+9xEEqV*W@YF4sySPgb|ceS0sCUVwP;@Ny=LNaK*zo7y}fx>jLXe^ z4i^{tTAiKeymgmt*3%2j(`hCa_NsT+xq0cPaKf`Qx+3g?3VAZyOqy4Z9ex{E zg}cx5cy+Y6z3lhq^VeZ>pT@KOATB1IJX<`kPX|QJ56@P%-?(cZyORNQ_DSZ~=O@dX zgK6Vx-U^t>xNM)?9l&6}=wCebR@+vc%9zq!v}t!UpC!_8}>yUDKXsy{ipJvew}^Xb`Y&mOb!Y1vx2R_cX8|B)Z5 z{+SysJNs8Jhp*4dh`al|FZ6S|jRz_8x-Wyxcre~{+LvYjuqU#iE!W|>(au|Q`fU1a zIGhibqt`q`dAMzldff>$?sI3@rh9m29({g(eRFaSB)@GBc`H8K@g2uwJ@ITWUl&se zyfN%F8;#aK@AGXjwYmp?tgl_+e%o3Z)^-@B`HriFD+>2{Srnh&3cjlF-F<97{=bneMJ6S+KR~z? z(NG;{j_4Q?=b(c|Rdr}_9smu8q3CmzS1q+jsHI${1o(qG99@WimbUK*-X%*(swtDy zSqv_nLD3Z4p*0J%Gfy-qY(bJh)ki0kEqPnpp!NxCe*bo8lImAcK7ZClWUlu#Lht z3peQ!!%j^qY!W^8OFxt>EUzsU(NbsI_I782TZ8?*k-c}W4}0YAOs*WELys1-ip}(0 zy}vW`Evh$1eGlZr`td_RO1B=SvU={H;rK8$e+QBM>W%I8S});v%TaDB0caLwGeI*hCz=C@h4 zEiv47Ehvk8*Y!Oft&UOE8>m)$=@6C4niR-F>#{6uX4sgFiee1nHU$DpL>V&xhTzg& z6G>c4n3Uvd6O;T192k{yDHyd^MoMxjCRmIv7i+55Ca~O*DWGkJ=xuZm3QLEQrwp8I z@KzTQn-)Zq literal 0 HcmV?d00001 diff --git a/tests/repository_data/repository/metadata.staged/role2.json b/tests/repository_data/repository/metadata.staged/role2.json new file mode 100644 index 0000000000000000000000000000000000000000..46e415a7892b9785f63f3e85e7015953804ffafa GIT binary patch literal 439 zcmYL_-D<-y42AFW6v5ZqkmdhA$F4R?k!_`fm9`|=SSfw?$qCy)zK|@=`E>4GujcW1 zrsZ?uS?&7wuJ7;idiBA#vC2f12#5n|PC1o~CXvs^W6pILD0!RMYpPhXPpKl?T;D6p_#VV4cXYHelC;FZ8Ux_&QE>*d^TY!|D;a=UUv zTxdG-GOygK@`;bMjF)qZ=P#PId2E+Wm(!NrzG=6a;_vIY1*#AXJcE{c1=y|iwn@)d bE{89kW)W|``USR+UjXsj8Vnsf(nwj)_F3CD_P} zG$uyts3Ix^EliTafK7~frLFWjcn*q#HH1qDzW$GGJbX+QjSG<&x7J(3geHzC?_I)0 zQL^NviQqJNr(~qsI?c7`O3IM5g`^o1hJck+QpE`+UQ-d1k3uDPCAb}7|ogs))gCK#VB(3ux ztd!0hWmq(VP$1StFPJCE7^{O-F6iXBHUi;jjOP`nDJe}2#-~YoZn?s>jw@qmFv)7B zA|}EI#SjH>BW$z+L*YR3#5tvcjoc`k1mRW?FrXt~COnJWIZABsz;&ctScEJ%w=$^6 zT;vi{izz~Q&T$)sj4E-w&=83dQhOjkICs@aYKvRPlTsuRD-d#Yj0OeVnZc zS%jmAHqqb^3&coj6euqVT%lAOJyt?;f-2!D7@X&tMxPW%Kr~Ql2%<}MB*V8)wV#m`Tjr&TV-@4- z59MZ=DvGQZi*ievdRXMexF}OzJ`}lI79*VaQUf}XabouCK<4|ShbM z=5V?iO~-BfOqz|0)?uS@o;B`FqnaNNPw{`NLE4kv;$}U$v?*J?E-uVXKi%iOX-2}a znwI0%aMgpO*5%>r=4CUfzd~1uPA1IaeA?d|u=z?XJCcs?^Ot#S z%a_Sh_q^Gkp2+9xEEqV*W@YF4sySPgb|ceS0sCUVwP;@Ny=LNaK*zo7y}fx>jLXe^ z4i^{tTAiKeymgmt*3%2j(`hCa_NsT+xq0cPaKf`Qx+3g?3VAZyOqy4Z9ex{E zg}cx5cy+Y6z3lhq^VeZ>pT@KOATB1IJX<`kPX|QJ56@P%-?(cZyORNQ_DSZ~=O@dX zgK6Vx-U^t>xNM)?9l&6}=wCebR@+vc%9zq!v}t!UpC!_8}>yUDKXsy{ipJvew}^Xb`Y&mOb!Y1vx2R_cX8|B)Z5 z{+SysJNs8Jhp*4dh`al|FZ6S|jRz_8x-Wyxcre~{+LvYjuqU#iE!W|>(au|Q`fU1a zIGhibqt`q`dAMzldff>$?sI3@rh9m29({g(eRFaSB)@GBc`H8K@g2uwJ@ITWUl&se zyfN%F8;#aK@AGXjwYmp?tgl_+e%o3Z)^-@B`HriFD+>2{Srnh&3cjlF-F<97{=bneMJ6S+KR~z? z(NG;{j_4Q?=b(c|Rdr}_9smu8q3CmzS1q+jsHI${1o(qG99@WimbUK*-X%*(swtDy zSqv_nLD3Z4p*0J%Gfy-qY(bJh)ki0kEqPnpp!NxCe*bo8lImAcK7ZClWUlu#Lht z3peQ!!%j^qY!W^8OFxt>EUzsU(NbsI_I782TZ8?*k-c}W4}0YAOs*WELys1-ip}(0 zy}vW`Evh$1eGlZr`td_RO1B=SvU={H;rK8$e+QW?RyKPOINUq4lKeaWvDZ+z}!-iXGLj-92>O3RL;APhLhsvKpH}q^;B{MB@l$t1t!zloSn1Z>@?}8PkAj zVyBcM>#+?kK&i vsb3eew6ScR6eZrM9Oj#ZGfhXH(?8l$LO~E||VCf2Hf2e zRaGq3@2AalJ?u_0zh3k@ecpV1+H8K?Z!>+@Ux#LIrWi1x3n(nT2g$`FdCBN0V=a(+ zRA@?CkW)=DWuLkdF_z>R*iU~f_3W5Y%@-8xwJ~y{^xTmH^-N}4-ISqLp(mWnEQ_bL97gR1>i}Nh8_~=S$ zy$eTTjVR645}BJ*DwTTci9HBtBw5R@ns4`V-EZZ%d$}Cu{qx!t>xm)Wiwp6l=>0k1 z!pWWnr*Vzetz5LZ5Rlg$nsw?ezZ=sjmehhDDcywM!|1h)^XJ6AI<7;(XP ze`S_@z0NPswr%mNDLQy;&ja&y6dWX{NOWU$Z`d?^w{&COb$8oX8%nM*^?;Sxx6IiE z=ma7miO1A(AOd(N&3nV;mzLcmnHFu`M{WN@C9=TMY*P{dTDHLMQ`A8#^0^=+vGF;TF1aZ+q0q^c!FnPGnxzVy z8wg{;K+)VCd_!hu3$@nVH2KOkf+gpjBfZ}Z?K@*mJ2eeKI(2KUp^!0p=fRm;=o*5Ezd5`ALh$Mtmm2Vl05dH?_b literal 0 HcmV?d00001 diff --git a/tests/repository_data/repository/metadata/1.root.json b/tests/repository_data/repository/metadata/1.root.json new file mode 100644 index 0000000000000000000000000000000000000000..ccce5381b64b408a996cb3e63b4a3edd99712f02 GIT binary patch literal 3394 zcmd5;*={385`3SpAo!{stL|ffeIQ#Db&;Z|gVL-Fp|0fJJi2vI#{BzclNwt#;N4kh z0h{2}RbAOpSs4-e%coks7!Pw-KCV+y|5E$cr&{e7{M72xv>8Vnsf(nwj)_F3CD_P} zG$uyts3Ix^EliTafK7~frLFWjcn*q#HH1qDzW$GGJbX+QjSG<&x7J(3geHzC?_I)0 zQL^NviQqJNr(~qsI?c7`O3IM5g`^o1hJck+QpE`+UQ-d1k3uDPCAb}7|ogs))gCK#VB(3ux ztd!0hWmq(VP$1StFPJCE7^{O-F6iXBHUi;jjOP`nDJe}2#-~YoZn?s>jw@qmFv)7B zA|}EI#SjH>BW$z+L*YR3#5tvcjoc`k1mRW?FrXt~COnJWIZABsz;&ctScEJ%w=$^6 zT;vi{izz~Q&T$)sj4E-w&=83dQhOjkICs@aYKvRPlTsuRD-d#Yj0OeVnZc zS%jmAHqqb^3&coj6euqVT%lAOJyt?;f-2!D7@X&tMxPW%Kr~Ql2%<}MB*V8)wV#m`Tjr&TV-@4- z59MZ=DvGQZi*ievdRXMexF}OzJ`}lI79*VaQUf}XabouCK<4|ShbM z=5V?iO~-BfOqz|0)?uS@o;B`FqnaNNPw{`NLE4kv;$}U$v?*J?E-uVXKi%iOX-2}a znwI0%aMgpO*5%>r=4CUfzd~1uPA1IaeA?d|u=z?XJCcs?^Ot#S z%a_Sh_q^Gkp2+9xEEqV*W@YF4sySPgb|ceS0sCUVwP;@Ny=LNaK*zo7y}fx>jLXe^ z4i^{tTAiKeymgmt*3%2j(`hCa_NsT+xq0cPaKf`Qx+3g?3VAZyOqy4Z9ex{E zg}cx5cy+Y6z3lhq^VeZ>pT@KOATB1IJX<`kPX|QJ56@P%-?(cZyORNQ_DSZ~=O@dX zgK6Vx-U^t>xNM)?9l&6}=wCebR@+vc%9zq!v}t!UpC!_8}>yUDKXsy{ipJvew}^Xb`Y&mOb!Y1vx2R_cX8|B)Z5 z{+SysJNs8Jhp*4dh`al|FZ6S|jRz_8x-Wyxcre~{+LvYjuqU#iE!W|>(au|Q`fU1a zIGhibqt`q`dAMzldff>$?sI3@rh9m29({g(eRFaSB)@GBc`H8K@g2uwJ@ITWUl&se zyfN%F8;#aK@AGXjwYmp?tgl_+e%o3Z)^-@B`HriFD+>2{Srnh&3cjlF-F<97{=bneMJ6S+KR~z? z(NG;{j_4Q?=b(c|Rdr}_9smu8q3CmzS1q+jsHI${1o(qG99@WimbUK*-X%*(swtDy zSqv_nLD3Z4p*0J%Gfy-qY(bJh)ki0kEqPnpp!NxCe*bo8lImAcK7ZClWUlu#Lht z3peQ!!%j^qY!W^8OFxt>EUzsU(NbsI_I782TZ8?*k-c}W4}0YAOs*WELys1-ip}(0 zy}vW`Evh$1eGlZr`td_RO1B=SvU={H;rK8$e+QBM>W%I8S});v%TaDB0caLwGeI*hCz=C@h4 zEiv47Ehvk8*Y!Oft&UOE8>m)$=@6C4niR-F>#{6uX4sgFiee1nHU$DpL>V&xhTzg& z6G>c4n3Uvd6O;T192k{yDHyd^MoMxjCRmIv7i+55Ca~O*DWGkJ=xuZm3QLEQrwp8I z@KzTQn-)Zq literal 0 HcmV?d00001 diff --git a/tests/repository_data/repository/metadata/role2.json b/tests/repository_data/repository/metadata/role2.json new file mode 100644 index 0000000000000000000000000000000000000000..46e415a7892b9785f63f3e85e7015953804ffafa GIT binary patch literal 439 zcmYL_-D<-y42AFW6v5ZqkmdhA$F4R?k!_`fm9`|=SSfw?$qCy)zK|@=`E>4GujcW1 zrsZ?uS?&7wuJ7;idiBA#vC2f12#5n|PC1o~CXvs^W6pILD0!RMYpPhXPpKl?T;D6p_#VV4cXYHelC;FZ8Ux_&QE>*d^TY!|D;a=UUv zTxdG-GOygK@`;bMjF)qZ=P#PId2E+Wm(!NrzG=6a;_vIY1*#AXJcE{c1=y|iwn@)d bE{89kW)W|``USR+UjXsj8Vnsf(nwj)_F3CD_P} zG$uyts3Ix^EliTafK7~frLFWjcn*q#HH1qDzW$GGJbX+QjSG<&x7J(3geHzC?_I)0 zQL^NviQqJNr(~qsI?c7`O3IM5g`^o1hJck+QpE`+UQ-d1k3uDPCAb}7|ogs))gCK#VB(3ux ztd!0hWmq(VP$1StFPJCE7^{O-F6iXBHUi;jjOP`nDJe}2#-~YoZn?s>jw@qmFv)7B zA|}EI#SjH>BW$z+L*YR3#5tvcjoc`k1mRW?FrXt~COnJWIZABsz;&ctScEJ%w=$^6 zT;vi{izz~Q&T$)sj4E-w&=83dQhOjkICs@aYKvRPlTsuRD-d#Yj0OeVnZc zS%jmAHqqb^3&coj6euqVT%lAOJyt?;f-2!D7@X&tMxPW%Kr~Ql2%<}MB*V8)wV#m`Tjr&TV-@4- z59MZ=DvGQZi*ievdRXMexF}OzJ`}lI79*VaQUf}XabouCK<4|ShbM z=5V?iO~-BfOqz|0)?uS@o;B`FqnaNNPw{`NLE4kv;$}U$v?*J?E-uVXKi%iOX-2}a znwI0%aMgpO*5%>r=4CUfzd~1uPA1IaeA?d|u=z?XJCcs?^Ot#S z%a_Sh_q^Gkp2+9xEEqV*W@YF4sySPgb|ceS0sCUVwP;@Ny=LNaK*zo7y}fx>jLXe^ z4i^{tTAiKeymgmt*3%2j(`hCa_NsT+xq0cPaKf`Qx+3g?3VAZyOqy4Z9ex{E zg}cx5cy+Y6z3lhq^VeZ>pT@KOATB1IJX<`kPX|QJ56@P%-?(cZyORNQ_DSZ~=O@dX zgK6Vx-U^t>xNM)?9l&6}=wCebR@+vc%9zq!v}t!UpC!_8}>yUDKXsy{ipJvew}^Xb`Y&mOb!Y1vx2R_cX8|B)Z5 z{+SysJNs8Jhp*4dh`al|FZ6S|jRz_8x-Wyxcre~{+LvYjuqU#iE!W|>(au|Q`fU1a zIGhibqt`q`dAMzldff>$?sI3@rh9m29({g(eRFaSB)@GBc`H8K@g2uwJ@ITWUl&se zyfN%F8;#aK@AGXjwYmp?tgl_+e%o3Z)^-@B`HriFD+>2{Srnh&3cjlF-F<97{=bneMJ6S+KR~z? z(NG;{j_4Q?=b(c|Rdr}_9smu8q3CmzS1q+jsHI${1o(qG99@WimbUK*-X%*(swtDy zSqv_nLD3Z4p*0J%Gfy-qY(bJh)ki0kEqPnpp!NxCe*bo8lImAcK7ZClWUlu#Lht z3peQ!!%j^qY!W^8OFxt>EUzsU(NbsI_I782TZ8?*k-c}W4}0YAOs*WELys1-ip}(0 zy}vW`Evh$1eGlZr`td_RO1B=SvU={H;rK8$e+QW?RyKPOINUq4lKeaWvDZ+z}!-iXGLj-92>O3RL;APhLhsvKpH}q^;B{MB@l$t1t!zloSn1Z>@?}8PkAj zVyBcM>#+?kK&i vsb3eew6ScR6eZrM9Oj#ZGfhXH(?8l$LO~E||VCf2Hf2e zRaGq3@2AalJ?u_0zh3k@ecpV1+H8K?Z!>+@Ux#LIrWi1x3n(nT2g$`FdCBN0V=a(+ zRA@?CkW)=DWuLkdF_z>R*iU~f_3W5Y%@-8xwJ~y{^xTmH^-N}4-ISqLp(mWnEQ_bL97gR1>i}Nh8_~=S$ zy$eTTjVR645}BJ*DwTTci9HBtBw5R@ns4`V-EZZ%d$}Cu{qx!t>xm)Wiwp6l=>0k1 z!pWWnr*Vzetz5LZ5Rlg$nsw?ezZ=sjmehhDDcywM!|1h)^XJ6AI<7;(XP ze`S_@z0NPswr%mNDLQy;&ja&y6dWX{NOWU$Z`d?^w{&COb$8oX8%nM*^?;Sxx6IiE z=ma7miO1A(AOd(N&3nV;mzLcmnHFu`M{WN@C9=TMY*P{dTDHLMQ`A8#^0^=+vGF;TF1aZ+q0q^c!FnPGnxzVy z8wg{;K+)VCd_!hu3$@nVH2KOkf+gpjBfZ}Z?K@*mJ2eeKI(2KUp^!0p=fRm;=o*5Ezd5`ALh$Mtmm2Vl05dH?_b literal 0 HcmV?d00001 diff --git a/tests/repository_data/repository/targets/file1.txt b/tests/repository_data/repository/targets/file1.txt new file mode 100644 index 00000000..7bf3499f --- /dev/null +++ b/tests/repository_data/repository/targets/file1.txt @@ -0,0 +1 @@ +This is an example target file. \ No newline at end of file diff --git a/tests/repository_data/repository/targets/file2.txt b/tests/repository_data/repository/targets/file2.txt new file mode 100644 index 00000000..606f18ef --- /dev/null +++ b/tests/repository_data/repository/targets/file2.txt @@ -0,0 +1 @@ +This is an another example target file. \ No newline at end of file diff --git a/tests/repository_data/repository/targets/file3.txt b/tests/repository_data/repository/targets/file3.txt new file mode 100644 index 00000000..60464604 --- /dev/null +++ b/tests/repository_data/repository/targets/file3.txt @@ -0,0 +1 @@ +This is role1's target file. \ No newline at end of file From 8de5c69f395c9e6e4d1cf4fb58c60a123f030b36 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Mon, 28 Aug 2017 16:13:05 -0400 Subject: [PATCH 20/24] Add check for supported major version of specification --- tuf/client/updater.py | 44 ++++++++++++++++++++++++++++++++----------- tuf/formats.py | 1 + 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/tuf/client/updater.py b/tuf/client/updater.py index 6b495b7a..ad811052 100755 --- a/tuf/client/updater.py +++ b/tuf/client/updater.py @@ -140,6 +140,10 @@ iso8601_logger = logging.getLogger('iso8601') iso8601_logger.disabled = True +# Metadata includes the specification version number that it follows. +# All downloaded metadata must be equal to our supported major version of 1. +# For example, "1.4.3" and "1.0.0" are supported. "2.0.0" is not supported. +SUPPORTED_MAJOR_VERSION = 1 class Updater(object): """ @@ -1060,6 +1064,23 @@ def _get_metadata_file(self, metadata_role, remote_filename, metadata_signable = \ securesystemslib.util.load_json_string(file_object.read().decode('utf-8')) + # Determine if the specification version number is supported. It is + # assumed that "spec_version" is in (major.minor.fix) format, (for + # example: "1.4.3") and that releases with the same major version + # number maintain backwards compatibility. Consequently, if the major + # version number of new metadata equals our expected major version + # number, the new metadata is safe to parse. + try: + spec_version_parsed = metadata_signable['spec_version'].split('.') + if int(spec_version_parsed[0]) != SUPPORTE_MAJOR_VERSION: + raise securesystemslib.exceptions.BadVersionNumberError('Downloaded' + ' metadata that specifies an unsupported spec_version. Supported' + ' major version number: ' + repr(SUPPORTED_MAJOR_VERSION)) + + except (ValueError, TypeError): + raise securesystemslib.excep4tions.FormatError('Improperly' + ' formatted spec_version, which must be in major.minor.fix format') + # If the version number is unspecified, ensure that the version number # downloaded is greater than the currently trusted version number for # 'metadata_role'. @@ -1261,7 +1282,7 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None): # Construct the metadata filename as expected by the download/mirror modules. metadata_filename = metadata_role + '.json' - uncompressed_metadata_filename = metadata_filename + metadata_filename = metadata_filename # Attempt a file download from each mirror until the file is downloaded and # verified. If the signature of the downloaded file is valid, proceed, @@ -1332,7 +1353,7 @@ def _update_metadata(self, metadata_role, upperbound_filelength, version=None): logger.debug('Updated ' + repr(current_filepath) + '.') self.metadata['previous'][metadata_role] = current_metadata_object self.metadata['current'][metadata_role] = updated_metadata_object - self._update_versioninfo(uncompressed_metadata_filename) + self._update_versioninfo(metadata_filename) # Ensure the role and key information of the top-level roles is also updated # according to the newly-installed Root metadata. @@ -1403,7 +1424,7 @@ def _update_metadata_if_changed(self, metadata_role, None. """ - uncompressed_metadata_filename = metadata_role + '.json' + metadata_filename = metadata_role + '.json' expected_versioninfo = None expected_fileinfo = None @@ -1427,25 +1448,26 @@ def _update_metadata_if_changed(self, metadata_role, # strictly greater than its currently trusted version number. expected_versioninfo = self.metadata['current'][referenced_metadata] \ ['meta'] \ - [uncompressed_metadata_filename] + [metadata_filename] - if not self._versioninfo_has_been_updated(uncompressed_metadata_filename, + if not self._versioninfo_has_been_updated(metadata_filename, expected_versioninfo): - logger.info(repr(uncompressed_metadata_filename) + ' up-to-date.') + logger.info(repr(metadata_filename) + ' up-to-date.') - # Since we have not downloaded a new version of this metadata, we - # should check to see if our local version is stale and notify the user - # if so. This raises tuf.exceptions.ExpiredMetadataError if the metadata we - # have is expired. Resolves issue #322. + # Since we have not downloaded a new version of this metadata, we should + # check to see if our local version is stale and notify the user if so. + # This raises tuf.exceptions.ExpiredMetadataError if the metadata we have + # is expired. Resolves issue #322. self._ensure_not_expired(self.metadata['current'][metadata_role], metadata_role) + # TODO: If 'metadata_role' is root or snapshot, we should verify that # root's hash matches what's in snapshot, and that snapshot hash matches # what's listed in timestamp.json. return - logger.debug('Metadata ' + repr(uncompressed_metadata_filename) + ' has changed.') + logger.debug('Metadata ' + repr(metadata_filename) + ' has changed.') # The file lengths of metadata are unknown, only their version numbers are # known. Set an upper limit for the length of the downloaded file for each diff --git a/tuf/formats.py b/tuf/formats.py index 70506b8a..cc63a43c 100755 --- a/tuf/formats.py +++ b/tuf/formats.py @@ -647,6 +647,7 @@ def make_metadata(version, expiration_date, filedict=None, delegations=None): result['version'] = version result['expires'] = expiration_date result['targets'] = {} + if filedict is not None: result['targets'] = filedict if delegations is not None: From 313169da1ac28cb4b64bd8cd062a16f15c6e1c1d Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Mon, 28 Aug 2017 16:57:52 -0400 Subject: [PATCH 21/24] Fix typo in code that checks for expected major version number --- tuf/client/updater.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tuf/client/updater.py b/tuf/client/updater.py index ad811052..0e058619 100755 --- a/tuf/client/updater.py +++ b/tuf/client/updater.py @@ -1071,8 +1071,8 @@ def _get_metadata_file(self, metadata_role, remote_filename, # version number of new metadata equals our expected major version # number, the new metadata is safe to parse. try: - spec_version_parsed = metadata_signable['spec_version'].split('.') - if int(spec_version_parsed[0]) != SUPPORTE_MAJOR_VERSION: + spec_version_parsed = metadata_signable['signed']['spec_version'].split('.') + if int(spec_version_parsed[0]) != SUPPORTED_MAJOR_VERSION: raise securesystemslib.exceptions.BadVersionNumberError('Downloaded' ' metadata that specifies an unsupported spec_version. Supported' ' major version number: ' + repr(SUPPORTED_MAJOR_VERSION)) From 6f8511a1a707fb024f4f1a84924a9dadcfccf2e6 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Mon, 28 Aug 2017 16:59:13 -0400 Subject: [PATCH 22/24] Add test condition for unsupported spec version number --- tests/test_updater.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/test_updater.py b/tests/test_updater.py index a8fbf9c8..9b82f5ff 100755 --- a/tests/test_updater.py +++ b/tests/test_updater.py @@ -694,7 +694,7 @@ def test_3__update_metadata(self): self.repository_updater.metadata['current']['targets']['version']) # Test: Invalid / untrusted version numbers. - # Invalid version number for the uncompressed version of 'targets.json'. + # Invalid version number for 'targets.json'. self.assertRaises(tuf.exceptions.NoWorkingMirrorError, self.repository_updater._update_metadata, 'targets', DEFAULT_TARGETS_FILELENGTH, 88) @@ -725,6 +725,37 @@ def test_3__update_metadata(self): + def test_3__get_metadata_file(self): + + valid_tuf_version = tuf.formats.TUF_VERSION_NUMBER + tuf.formats.TUF_VERSION_NUMBER = '2' + + repository = repo_tool.load_repository(self.repository_directory) + + repository.root.load_signing_key(self.role_keys['root']['private']) + repository.targets.load_signing_key(self.role_keys['targets']['private']) + repository.snapshot.load_signing_key(self.role_keys['snapshot']['private']) + repository.timestamp.load_signing_key(self.role_keys['timestamp']['private']) + repository.writeall() + + # Move the staged metadata to the "live" metadata. + shutil.rmtree(os.path.join(self.repository_directory, 'metadata')) + shutil.copytree(os.path.join(self.repository_directory, 'metadata.staged'), + os.path.join(self.repository_directory, 'metadata')) + + upperbound_filelength = tuf.settings.DEFAULT_ROOT_REQUIRED_LENGTH + self.assertRaises(tuf.exceptions.NoWorkingMirrorError, + self.repository_updater._get_metadata_file, 'root', 'root.json', + upperbound_filelength, 1) + + # Reset the TUF_VERSION_NUMBER so that subsequent unit tests use the + # expected value. + tuf.formats.TUF_VERSION_NUMBER = valid_tuf_version + + + + + def test_3__update_metadata_if_changed(self): # Setup. # The client repository is initially loaded with only four top-level roles. From 0ff07186a968139553cbf149fe17072c6fbdb8a1 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Mon, 28 Aug 2017 17:31:25 -0400 Subject: [PATCH 23/24] Add spec_version to tuf-spec.md --- docs/tuf-spec.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/tuf-spec.md b/docs/tuf-spec.md index 8bdb295f..6fd722a5 100644 --- a/docs/tuf-spec.md +++ b/docs/tuf-spec.md @@ -534,6 +534,7 @@ Version: **1.0 (Draft)** The "signed" portion of root.json is as follows: { "_type" : "root", + "spec_version" : SPEC_VERSION, "consistent_snapshot": CONSISTENT_SNAPSHOT, "version" : VERSION, "expires" : EXPIRES, @@ -547,6 +548,13 @@ Version: **1.0 (Draft)** , ... } } + SPEC_VERSION is the version number of the specification. Metadata is + written according to version "spec_version" of the specification, and + clients MUST verify that "spec_version" matches the expected version number. + Adopters are free to determine what is considered a match (e.g., the version + number must exactly exactly, or perhaps only the major version number + (major.minor.fix). + CONSISTENT_SNAPSHOT is a boolean indicating whether the repository supports consistent snapshots. Section 7 goes into more detail on the consequences of enabling this setting on a repository. @@ -585,6 +593,7 @@ Version: **1.0 (Draft)** ], "signed": { "_type": "root", + "spec_version": "1", "consistent_snapshot": false, "expires": "2030-01-01T00:00:00Z", "keys": { @@ -657,6 +666,7 @@ Version: **1.0 (Draft)** The "signed" portion of snapshot.json is as follows: { "_type" : "snapshot", + "spec_version" : SPEC_VERSION, "version" : VERSION, "expires" : EXPIRES, "meta" : METAFILES @@ -687,6 +697,7 @@ Version: **1.0 (Draft)** ], "signed": { "_type": "snapshot", + "spec_version": "1", "expires": "2030-01-01T00:00:00Z", "meta": { "root.json": { @@ -708,6 +719,7 @@ Version: **1.0 (Draft)** The "signed" portion of targets.json is as follows: { "_type" : "targets", + "spec_version" : SPEC_VERSION, "version" : VERSION, "expires" : EXPIRES, "targets" : TARGETS, @@ -816,6 +828,7 @@ Version: **1.0 (Draft)** ], "signed": { "_type": "targets", + "spec_version": "1", "delegations": { "keys": { "ce3e02e72980b09ca6f5efa68197130b381921e5d0675e2e0c8f3c47e0626bba": { @@ -871,6 +884,7 @@ Version: **1.0 (Draft)** The "signed" portion of timestamp.json is as follows: { "_type" : "timestamp", + "spec_version" : SPEC_VERSION, "version" : VERSION, "expires" : EXPIRES, "meta" : METAFILES @@ -892,6 +906,7 @@ Version: **1.0 (Draft)** ], "signed": { "_type": "timestamp", + "spec_version": "1", "expires": "2030-01-01T00:00:00Z", "meta": { "snapshot.json": { @@ -916,6 +931,7 @@ Version: **1.0 (Draft)** { "_type" : "mirrors", + "spec_version" : SPEC_VERSION, "version" : VERSION, "expires" : EXPIRES, "mirrors" : [ From c897a43238c358676503f08ac0297bc48692d523 Mon Sep 17 00:00:00 2001 From: Vladimir Diaz Date: Tue, 29 Aug 2017 09:54:31 -0400 Subject: [PATCH 24/24] Add valid developer_tool.py metadata --- .../project/test-flat/role1.json | Bin 716 -> 741 bytes .../project/test-flat/test-flat.json | Bin 2197 -> 2222 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/repository_data/project/test-flat/role1.json b/tests/repository_data/project/test-flat/role1.json index 6ba90f89cd15accc4e15d6180cf938267d36e296..db887f1d8346de85ba72c54198a5a47494e63888 100644 GIT binary patch delta 164 zcmWNJyA1*{3_x|oO~3-^20(T`j>8_*$VqI82GE^!lng)vv#JB_hWsi30|;OP8;oEB8yG+VjDY!^-lzNJ3K@;VlV)0h zOiX9BFbOzyhWbJ(57nIt?17PJ1d1*tI=~ybf>zpUE-72eba@LW+pKM{2d^Gd>KOlI TS`W-1E+#ta@x8sC$NBgH-K;6= diff --git a/tests/repository_data/project/test-flat/test-flat.json b/tests/repository_data/project/test-flat/test-flat.json index 1240e34d0179bd05e11b45310b001e31940a1507..2457b94f30b6c679182f7d55c2ef247464fffe44 100644 GIT binary patch delta 811 zcmWlXO{yI>429tZ-aI4=2w6a}B`5$ zEX!-9sJW~rUYIAKgu#w%b}o(bJk}33au!!eZQjn8P3PV{^Psy`S6G2(DN>-^8;E!m z;GUH}>c?l#K1rFEYK0nSUn%wEtEj$GSx0BH(&7Tf&h*2J86Q~VBku~LjkXR%m}Ku1 znCZ35he`&>3E$;0G?WkcmDBgim1N^yy8O94INbq=bwyJ*jXBM|cgeD9KF9;wVvh#0 zjp0Y_JCDOrZCyKu#B=PEQeQZ_j~G8yTo6>Nh#_DR@UiHm<_@|?bYjs12jJin(mVI*|Jg&qiFny@VbI;9YMq;A$@3bJ=~6 zvQF;YQ_yiVf!=c`&P|(`ZjWq8nZ&*jGXGB8>35BF#)${#md-&*-r z#13n5IBcN2DrHCQI777yIO1=is6SYoQ)FVSq+jME8neQz?#hVWj$*!+Mkt*%qf@n} z_oqAo{Mr6zX{I6Fa(!Eqn7ZaIQ(Fa1cvn$I#uyX%g~}@Q>Rb9185W(j%HquRm@d8z z#NE`m!As`Va!r0#I*ZrS52G2Ip3ghZk00)B<{LSsa#yLWF;MOv6ZRE%&-g&(t z5syRfjazO1p}5%h=B)J?ZGP{mN4?PlXbM%A^)*FrA_pDN1mZtw^K|U@uRs3%@tgkq G>&O3LOWY3t