@@ -1896,22 +1896,26 @@ def add_paths(self, paths, child_rolename):
18961896 def add_target (self , filepath , custom = None ):
18971897 """
18981898 <Purpose>
1899- Add a filepath (must be located in the repository's targets directory) to
1900- the Targets object.
1899+ Add a filepath (must be relative to the repository's targets directory)
1900+ to the Targets object.
19011901
1902- This method does not actually create 'filepath' on the file system.
1903- 'filepath' must already exist on the file system. If 'filepath'
1904- has already been added, it will be replaced with any new file
1905- or 'custom' information.
1902+ This method does not access the file system. 'filepath' must already
1903+ exist on the file system.
1904+
1905+ If 'filepath' does not exist the file will still be added to 'roleinfo'.
1906+ Only later calls to write() and writeall() will fail.
1907+
1908+ If 'filepath' has already been added, it will be replaced with any new
1909+ file or 'custom' information.
19061910
19071911 >>>
19081912 >>>
19091913 >>>
19101914
19111915 <Arguments>
19121916 filepath:
1913- The path of the target file. It must exist in the repository's targets
1914- directory.
1917+ The path of the target file. It must be relative to the repository's
1918+ targets directory.
19151919
19161920 custom:
19171921 An optional object providing additional information about the file.
@@ -1920,8 +1924,8 @@ def add_target(self, filepath, custom=None):
19201924 securesystemslib.exceptions.FormatError, if 'filepath' is improperly
19211925 formatted.
19221926
1923- securesystemslib .exceptions.Error , if 'filepath' is not located in the
1924- repository's targets directory.
1927+ tuf .exceptions.InvalidNameError , if 'filepath' is not relative (starts
1928+ with a directory separator) .
19251929
19261930 <Side Effects>
19271931 Adds 'filepath' to this role's list of targets. This role's
@@ -1935,47 +1939,38 @@ def add_target(self, filepath, custom=None):
19351939 # Ensure the arguments have the appropriate number of objects and object
19361940 # types, and that all dict keys are properly named. Raise
19371941 # 'securesystemslib.exceptions.FormatError' if there is a mismatch.
1938- securesystemslib .formats .PATH_SCHEMA .check_match (filepath )
1942+ tuf .formats .RELPATH_SCHEMA .check_match (filepath )
19391943
19401944 if custom is None :
19411945 custom = {}
1942-
19431946 else :
19441947 tuf .formats .CUSTOM_SCHEMA .check_match (custom )
19451948
1946- filepath = os .path .join (self ._targets_directory , filepath )
1947-
19481949 # Add 'filepath' (i.e., relative to the targets directory) to the role's
19491950 # list of targets. 'filepath' will not be verified as an allowed path
19501951 # according to some delegating role. Not verifying 'filepath' here allows
19511952 # freedom to add targets and parent restrictions in any order, minimize the
19521953 # number of times these checks are performed, and allow any role to
1953- # delegate trust of packages to this Targes role.
1954- if os .path .isfile (filepath ):
1955-
1956- # Update the role's 'tuf.roledb.py' entry and avoid duplicates. Make
1957- # sure to exclude the path separator when calculating the length of the
1958- # targets directory.
1959- targets_directory_length = len (self ._targets_directory ) + 1
1960- roleinfo = tuf .roledb .get_roleinfo (self ._rolename , self ._repository_name )
1961- relative_path = filepath [targets_directory_length :].replace ('\\ ' , '/' )
1954+ # delegate trust of packages to this Targets role.
19621955
1963- if relative_path not in roleinfo ['paths' ]:
1964- logger .debug ('Adding new target: ' + repr (relative_path ))
1965- roleinfo ['paths' ].update ({relative_path : custom })
1966-
1967- else :
1968- logger .debug ('Replacing target: ' + repr (relative_path ))
1969- roleinfo ['paths' ].update ({relative_path : custom })
1956+ # Check if the target path is relative and normalize it. File's existence
1957+ # on the file system is not verified. If the file does not exist relative
1958+ # to the targets directory, later calls to write() will fail.
1959+ relative_path = self ._check_relpath (filepath )
19701960
1961+ # Update the role's 'tuf.roledb.py' entry and avoid duplicates.
1962+ roleinfo = tuf .roledb .get_roleinfo (self ._rolename , self ._repository_name )
19711963
1972- tuf .roledb .update_roleinfo (self ._rolename , roleinfo ,
1973- repository_name = self ._repository_name )
1964+ if relative_path not in roleinfo ['paths' ]:
1965+ logger .debug ('Adding new target: ' + repr (relative_path ))
1966+ roleinfo ['paths' ].update ({relative_path : custom })
19741967
19751968 else :
1976- raise securesystemslib .exceptions .Error (repr (filepath ) + ' is not'
1977- ' a valid file in the repository\' s targets'
1978- ' directory: ' + repr (self ._targets_directory ))
1969+ logger .debug ('Replacing target: ' + repr (relative_path ))
1970+ roleinfo ['paths' ].update ({relative_path : custom })
1971+
1972+ tuf .roledb .update_roleinfo (self ._rolename , roleinfo ,
1973+ repository_name = self ._repository_name )
19791974
19801975
19811976
@@ -1999,9 +1994,8 @@ def add_targets(self, list_of_targets):
19991994 securesystemslib.exceptions.FormatError, if the arguments are improperly
20001995 formatted.
20011996
2002- securesystemslib.exceptions.Error, if any of the paths listed in
2003- 'list_of_targets' is not located in the repository's targets directory or
2004- is invalid.
1997+ tuf.exceptions.InvalidNameError, if any target in 'list_of_targets'
1998+ is not relative (starts with a directory separator).
20051999
20062000 <Side Effects>
20072001 This Targets' roleinfo is updated with the paths in 'list_of_targets'.
@@ -2017,7 +2011,6 @@ def add_targets(self, list_of_targets):
20172011 tuf .formats .RELPATHS_SCHEMA .check_match (list_of_targets )
20182012
20192013 # Update the tuf.roledb entry.
2020- targets_directory_length = len (self ._targets_directory )
20212014 relative_list_of_targets = []
20222015
20232016 # Ensure the paths in 'list_of_targets' are valid and are located in the
@@ -2027,15 +2020,7 @@ def add_targets(self, list_of_targets):
20272020 # freedom to add targets and parent restrictions in any order, and minimize
20282021 # the number of times these checks are performed.
20292022 for target in list_of_targets :
2030- filepath = os .path .join (self ._targets_directory , target )
2031-
2032- if os .path .isfile (filepath ):
2033- relative_list_of_targets .append (
2034- filepath [targets_directory_length + 1 :].replace ('\\ ' , '/' ))
2035-
2036- else :
2037- raise securesystemslib .exceptions .Error (repr (filepath ) + ' is not'
2038- ' a valid file.' )
2023+ relative_list_of_targets .append (self ._check_relpath (target ))
20392024
20402025 # Update this Targets 'tuf.roledb.py' entry.
20412026 roleinfo = tuf .roledb .get_roleinfo (self ._rolename , self ._repository_name )
@@ -2223,12 +2208,11 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
22232208 securesystemslib.exceptions.FormatError, if any of the arguments are
22242209 improperly formatted.
22252210
2226- securesystemslib.exceptions.Error, if the delegated role already exists
2227- or if any target in 'list_of_targets' is an invalid path (i.e., not
2228- located in the repository's targets directory).
2211+ securesystemslib.exceptions.Error, if the delegated role already exists.
22292212
2230- tuf.exceptions.InvalidNameError, if any path in 'paths' is not a
2231- relative path (starts with a directory separator).
2213+ tuf.exceptions.InvalidNameError, if any path in 'paths' or any
2214+ target in 'list_of_targets' is not relative (starts with a directory
2215+ separator).
22322216
22332217 <Side Effects>
22342218 A new Target object is created for 'rolename' that is accessible to the
@@ -2274,16 +2258,15 @@ def delegate(self, rolename, public_keys, paths, threshold=1,
22742258 # Ensure the paths of 'list_of_targets' are located in the repository's
22752259 # targets directory.
22762260 relative_targetpaths = {}
2277- targets_directory_length = len (self ._targets_directory )
22782261
22792262 if list_of_targets :
22802263 for target in list_of_targets :
2281- target = os . path . join ( self . _targets_directory , target )
2282- if not os . path . isfile ( target ):
2283- logger . warning ( repr ( target ) + ' does not exist in the'
2284- ' repository \' s targets directory: ' + repr ( self . _targets_directory ))
2285-
2286- relative_targetpaths .update ({target [ targets_directory_length :] : {}})
2264+ # Check if the target path is relative and normalize it. File's
2265+ # existence on the file system is not verified. If the file does not
2266+ # exist relative to the targets directory, later calls to write()
2267+ # will fail.
2268+ rel_targetpath = self . _check_relpath ( target )
2269+ relative_targetpaths .update ({rel_targetpath : {}})
22872270
22882271 # A list of relative and verified paths or glob patterns to be added to the
22892272 # child role's entry in the parent's delegations field.
@@ -2468,9 +2451,12 @@ def delegate_hashed_bins(self, list_of_targets, keys_of_hashed_bins,
24682451 formatted.
24692452
24702453 securesystemslib.exceptions.Error, if 'number_of_bins' is not a power of
2471- 2, or one of the targets in 'list_of_targets' is not located in the
2454+ 2, or one of the targets in 'list_of_targets' is not relative to the
24722455 repository's targets directory.
24732456
2457+ tuf.exceptions.InvalidNameError, if any target in 'list_of_targets'
2458+ is not relative (starts with a directory separator).
2459+
24742460 <Side Effects>
24752461 Delegates multiple target roles from the current parent role.
24762462
@@ -2518,17 +2504,12 @@ def delegate_hashed_bins(self, list_of_targets, keys_of_hashed_bins,
25182504 for bin_index in six .moves .xrange (total_hash_prefixes ):
25192505 target_paths_in_bin [bin_index ] = []
25202506
2521- # Assign every path to its bin. Log a warning if the target path does not
2522- # exist in the repository's targets directory.
2507+ # Assign every path to its bin.
25232508 for target_path in list_of_targets :
2524- if not os .path .isfile (os .path .join (self ._targets_directory , target_path )):
2525- logger .warning ('A path in "list of'
2526- ' targets" is not located in the repository\' s targets'
2527- ' directory: ' + repr (target_path ))
2528-
2529- else :
2530- logger .debug (repr (target_path ) + ' is located in the repository\' s'
2531- ' targets directory.' )
2509+ # Check if the target path is relative and normalize it. File's existence
2510+ # on the file system is not verified. If the file does not exist relative
2511+ # to the targets directory, later calls to write() will fail.
2512+ target_path = self ._check_relpath (target_path )
25322513
25332514 # Determine the hash prefix of 'target_path' by computing the digest of
25342515 # its path relative to the targets directory. Example:
@@ -2736,11 +2717,10 @@ def _locate_and_update_target_in_bin(self, target_filepath, method_name):
27362717 raise securesystemslib .exceptions .Error (self .rolename + ' has not'
27372718 ' delegated to hashed bins.' )
27382719
2739- # Log warning if 'target_filepath' is not located in the repository's
2740- # targets directory.
2741- if not os .path .isfile (os .path .join (self ._targets_directory , target_filepath )):
2742- logger .warning (repr (target_filepath ) + ' is not located in the'
2743- ' repository\' s targets directory: ' + repr (self ._targets_directory ))
2720+ # Check if the target path is relative and normalize it. File's existence
2721+ # on the file system is not verified. If the file does not exist relative
2722+ # to the targets directory, later calls to write() will fail.
2723+ target_filepath = self ._check_relpath (target_filepath )
27442724
27452725 # Determine the hash prefix of 'target_path' by computing the digest of
27462726 # its path relative to the targets directory. Example:
0 commit comments