From ccec85c5f039b941f72db3123a53ea996a6789cb Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Wed, 11 Sep 2024 15:57:38 +0200 Subject: [PATCH] common: set revision according to remote url and branch The previous implementation was setting the revision of a project according to only the remote url. Indeed getRevision returned a list of url - revision. But that doesn't work if a remote url is used several times with different path/branch. Example: project A: remote url X, branch Y, path project-a-path project B: remote url X, branch Z, path project-b-path With the previous implementation, both projects will get the same revision since they are using same remote url (same entry in the revisionTable). To fix this issue, we now check the remote url AND the branch. getRevision return the url, revision AND the branch, the branch returned doesn't contain any suffix (tags ...). Signed-off-by: Julien Masson --- repo_resource/common.py | 42 ++++++++++++++++++++++++------------- repo_resource/test_check.py | 17 +++++++++++++++ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/repo_resource/common.py b/repo_resource/common.py index 9fe16f7..6bea21c 100644 --- a/repo_resource/common.py +++ b/repo_resource/common.py @@ -94,20 +94,24 @@ def getRevision(remote, remoteUrl, project, branch): with git ls-remote command for each project without downloading the whole repo """ - # v1.0^{} is the commit referring to tag v1.0 - # git ls-remote returns the tag sha1 if left as is - if branch.startswith('refs/tags'): - branch += '^{}' try: with redirect_stdout(sys.stderr): - # return tuple (remote/project, revision) - print('Fetching revision for {}/{}...'.format(remote, project)) + # return tuple (remote/project, branch, revision) + print('Fetching revision for {}/{} - {}...'.format( + remote, project, branch)) if is_sha1(branch): - return (remote + '/' + project, branch) + return (remote + '/' + project, branch, branch) g = git.cmd.Git() + + headRef = branch + # v1.0^{} is the commit referring to tag v1.0 + # git ls-remote returns the tag sha1 if left as is + if branch.startswith('refs/tags'): + headRef += '^{}' + url, revList = ( remote + '/' + project, - g.ls_remote(remoteUrl+'/'+project, branch).split() + g.ls_remote(remoteUrl+'/'+project, headRef).split() ) # convert revision list to revision dict: @@ -117,12 +121,14 @@ def getRevision(remote, remoteUrl, project, branch): for a, b in zip(revList[::2], revList[1::2])]) if branch.startswith('refs/tags'): - rev = branch + rev = headRef else: rev = 'refs/heads/' + branch - print('{}: {}'.format(url, revDict[rev])) - return (url, revDict[rev]) + print('{} - {}: {}'.format(url, branch, revDict[rev])) + + # return url, branch (without any suffix) and revision + return (url, branch, revDict[rev]) except Exception as e: with redirect_stdout(sys.stderr): print('Cannot fetch project {}/{}'.format(remoteUrl, project)) @@ -462,15 +468,21 @@ def update_manifest(self, jobs): with Pool(jobs) as pool: revisionList = pool.map(multi_run_wrapper, projects) - # Convert (remote/project, revision) tuple list - # to hash table dict[remote/project]=revision - revisionTable = dict((proj, rev) for proj, rev in revisionList) # Update revisions for p in manifest.findall('project'): project = p.get('name') + projectBranch = p.get('revision') or defaultBranch projectRemote = p.get('remote') or defaultRemote - p.set('revision', revisionTable[projectRemote+'/'+project]) + # find revision of the project in revisionList + for url, branch, rev in revisionList: + if ( + projectRemote + "/" + project == url + and branch == projectBranch + ): + projectRev = rev + break + p.set('revision', projectRev) self.__version = Version( ET.canonicalize( diff --git a/repo_resource/test_check.py b/repo_resource/test_check.py index 7bee074..e1084e3 100644 --- a/repo_resource/test_check.py +++ b/repo_resource/test_check.py @@ -99,6 +99,13 @@ def setUp(self): 'name': 'branch_matching.xml' } } + self.one_project_multi_path_source = { + 'source': { + 'url': 'https://github.com/makohoek/demo-manifests.git', + 'revision': 'main', + 'name': 'one_project_multi_path.xml' + } + } def tearDown(self): p = common.CACHEDIR @@ -454,6 +461,16 @@ def test_branch_matching(self): version = versions[0]['version'] self.assertEqual(version, expected_version) + def test_one_project_multi_path(self): + data = self.one_project_multi_path_source + instream = StringIO(json.dumps(data)) + versions = check.check(instream) + + expected_version = '' # noqa: E501 + + version = versions[0]['version'] + self.assertEqual(version, expected_version) + if __name__ == '__main__': unittest.main()