From e0f7afc43c5e269f7b7357aaf4550fc8ec4c39ee Mon Sep 17 00:00:00 2001 From: Robert Cowham Date: Mon, 25 Nov 2024 13:31:58 +0000 Subject: [PATCH] Cope with different src/targ depot paths in CompareRepos --- CompareRepos.py | 46 ++++++++++++++++++++++------ test/TestCompareRepos.py | 66 ++++++++++++++++++++++++++++++++++------ 2 files changed, 92 insertions(+), 20 deletions(-) diff --git a/CompareRepos.py b/CompareRepos.py index 7990a30..e5e9c62 100755 --- a/CompareRepos.py +++ b/CompareRepos.py @@ -153,6 +153,17 @@ def __init__(self, *args): caseSensitiveServer = self.config['case_sensitive'] # If true we have to adjust things inconsistentCase = caseSensitiveOS and not caseSensitiveServer + # Setup for comparing different source/target paths e.g. //srcDepot/... -> //targDepot/... + self.srcPath = self.options.source + self.targPath = self.options.target + if "@" in self.srcPath: + parts = self.srcPath.split("@") + if len(parts) > 1: + self.srcPath = parts[0] + if self.srcPath.endswith("/..."): + self.srcPath = self.srcPath[0:len(self.srcPath)-3] + if self.targPath.endswith("/..."): + self.targPath = self.targPath[0:len(self.targPath)-3] def getFiles(self, fstat): # Returns 2 lists: depot files and local files @@ -211,45 +222,60 @@ def run(self): # Note that for inconsistentCase operation, keys to these dicts are lowercase srcDepotFiles, srcLocalFiles = self.getFiles(srcFstat) targDepotFiles, targLocalFiles = self.getFiles(targFstat) + targLookupFiles = {} + for k, v in targDepotFiles.items(): + if self.srcPath == self.targPath: + targLookupFiles[k] = v + else: + targLookupFiles[k.replace(self.targPath, self.srcPath)] = v missing = [] deleted = [] extras = [] different = [] for k, v in srcDepotFiles.items(): if 'delete' not in v.action and v.action != 'purge': - if k not in targDepotFiles: + if k not in targLookupFiles: missing.append(k) if self.options.fix: - print("missing: %s; %s" % (k, v.depotFile)) + d = v.depotFile + if self.srcPath != self.targPath: + d = d.replace(self.srcPath, self.targPath) + print(f"missing: {k}; {d}") if k not in srcLocalHaveFiles: # Otherwise we assume already manually synced nfile = escapeWildcards(srcLocalFiles[k]) print("src: %s" % self.srcp4.run_sync('-f', "%s#%s" % (nfile, v.rev))) print(self.targp4.run_add('-ft', v.type, srcLocalFiles[k])) - if k in targDepotFiles and 'delete' in targDepotFiles[k].action: - deleted.append((k, targDepotFiles[k].change)) + if k in targLookupFiles and 'delete' in targLookupFiles[k].action: + deleted.append((k, targLookupFiles[k].change)) if self.options.fix: - print("deleted: %s; %s" % (k, v.depotFile)) + d = v.depotFile + if self.srcPath != self.targPath: + d = d.replace(self.srcPath, self.targPath) + print(f"deleted: {k}; {d}") print(self.srcp4.run_sync('-f', "%s#%s" % (escapeWildcards(srcLocalFiles[k]), v.rev))) if inconsistentCase and srcLocalFiles[k] != targLocalFiles[k]: self.copyLocalFile(srcLocalFiles[k], targLocalFiles[k]) print(self.targp4.run_add('-ft', v.type, srcLocalFiles[k])) if 'delete' not in v.action and v.action != 'purge': - if k in targDepotFiles and 'delete' not in targDepotFiles[k].action and v.digest != targDepotFiles[k].digest: - different.append((k, v, targDepotFiles[k])) + if k in targLookupFiles and 'delete' not in targLookupFiles[k].action and v.digest != targLookupFiles[k].digest: + different.append((k, v, targLookupFiles[k])) if self.options.fix: - print("different: %s; %s" % (k, v.depotFile)) + d = v.depotFile + if self.srcPath != self.targPath: + d = d.replace(self.srcPath, self.targPath) + print(f"different: {k}; {d}") with self.targp4.at_exception_level(P4.P4.RAISE_NONE): print(self.targp4.run_sync("-k", targLocalFiles[k])) print(self.srcp4.run_sync('-f', "%s#%s" % (escapeWildcards(srcLocalFiles[k]), v.rev))) if inconsistentCase and srcLocalFiles[k] != targLocalFiles[k]: self.copyLocalFile(srcLocalFiles[k], targLocalFiles[k]) print(self.targp4.run_edit('-t', v.type, escapeWildcards(srcLocalFiles[k]))) - for k, v in targDepotFiles.items(): + for k, v in targLookupFiles.items(): if 'delete' not in v.action: if k not in srcDepotFiles or (k in srcDepotFiles and 'delete' in srcDepotFiles[k].action): extras.append(k) if self.options.fix: - print("extra: %s; %s" % (k, v.depotFile)) + print(f"extra: {targDepotFiles[k].depotFile}; {v.depotFile}") with self.targp4.at_exception_level(P4.P4.RAISE_NONE): print(self.targp4.run_sync('-k', escapeWildcards(targLocalFiles[k]))) print(self.targp4.run_delete(escapeWildcards(targLocalFiles[k]))) diff --git a/test/TestCompareRepos.py b/test/TestCompareRepos.py index 6791bd3..0d235d1 100644 --- a/test/TestCompareRepos.py +++ b/test/TestCompareRepos.py @@ -254,32 +254,46 @@ def cleanupTestTree(self): if os.path.isdir(self.transfer_root): shutil.rmtree(self.transfer_root, False, onRmTreeError) - def getDefaultOptions(self): + def getDefaultOptions(self, srcDepot="depot", targDepot="depot"): config = {} config['transfer_client'] = TRANSFER_CLIENT config['workspace_root'] = self.transfer_client_root - config['views'] = [{'src': '//depot/...', - 'targ': '//depot/...'}] + config['views'] = [{'src': f'//{srcDepot}/...', + 'targ': f'//{targDepot}/...'}] return config - def setupCompare(self): + def setupCompare(self, srcDepot="depot", targDepot="depot"): """Creates a config file with default mappings""" msg = "Test: %s ======================" % inspect.stack()[1][3] self.logger.debug(msg) - config = self.getDefaultOptions() + config = self.getDefaultOptions(srcDepot=srcDepot, targDepot=targDepot) self.createConfigFile(options=config) - client = self.source.p4.fetch_client(config['transfer_client']) + if srcDepot != "depot": + clientName = P4CLIENT + client = self.source.p4.fetch_client(clientName) + client._root = self.source.client_root + client._view = [f'//{srcDepot}/... //{clientName}/...'] + self.source.p4.save_client(client) + if targDepot != "depot": + clientName = P4CLIENT + client = self.target.p4.fetch_client(clientName) + client._root = self.target.client_root + client._view = [f'//{targDepot}/... //{clientName}/...'] + self.target.p4.save_client(client) + + clientName = config['transfer_client'] + client = self.source.p4.fetch_client(clientName) client._root = config['workspace_root'] - client._view = ['//depot/... //%s/depot/...' % (config['transfer_client'])] + client._view = [f'//{srcDepot}/... //{clientName}/{srcDepot}/...'] self.source.p4.save_client(client) - client = self.target.p4.fetch_client(config['transfer_client']) + client = self.target.p4.fetch_client(clientName) client._root = config['workspace_root'] - client._view = ['//depot/... //%s/depot/...' % (config['transfer_client'])] + client._view = [f'//{targDepot}/... //{clientName}/{srcDepot}/...'] self.target.p4.save_client(client) self.transferp4 = P4.P4() self.transferp4.port = self.target.p4.port self.transferp4.user = self.target.p4.user - self.transferp4.client = config['transfer_client'] + self.transferp4.client = clientName self.transferp4.connect() def createConfigFile(self, srcOptions=None, targOptions=None, options=None): @@ -459,6 +473,38 @@ def testAddWithHave(self): self.assertEqual(1, len(files)) self.assertEqual('//depot/inside/inside_file1', files[0]['depotFile']) + def testAddDifferentDepots(self): + "Basic file add with different source/target depot names" + # Create new depots + srcDepot = 'srcDepot' + targDepot = 'targDepot' + d = self.source.p4.fetch_depot(srcDepot) + self.source.p4.save_depot(d) + self.source.p4.disconnect() + self.source.p4.connect() + d = self.target.p4.fetch_depot(targDepot) + self.target.p4.save_depot(d) + self.target.p4.disconnect() + self.target.p4.connect() + self.setupCompare(srcDepot=srcDepot, targDepot=targDepot) + + inside = localDirectory(self.source.client_root, "inside") + inside_file1 = os.path.join(inside, "inside_file1") + create_file(inside_file1, 'Test content') + + self.source.p4cmd('add', inside_file1) + self.source.p4cmd('submit', '-d', 'inside_file1 added') + + self.run_CompareRepos('-s', f'//{srcDepot}/...@3', '-t', f'//{targDepot}/...', '--fix') + self.transferp4.run('submit', '-d', "Target") + + changes = self.target.p4cmd('changes') + self.assertEqual(1, len(changes)) + + files = self.target.p4cmd('files', f'//{targDepot}/...') + self.assertEqual(1, len(files)) + self.assertEqual(f'//{targDepot}/inside/inside_file1', files[0]['depotFile']) + def testAddWithHaveWildcard(self): "Basic file add where source files already synced" self.setupCompare()