diff options
-rw-r--r-- | modules/llvm.py | 42 | ||||
-rw-r--r-- | scripts/llvm.py | 6 | ||||
-rw-r--r-- | tests/unittests/testllvmsourceconfig.py | 150 |
3 files changed, 158 insertions, 40 deletions
diff --git a/modules/llvm.py b/modules/llvm.py index 298076d..953b513 100644 --- a/modules/llvm.py +++ b/modules/llvm.py @@ -73,7 +73,7 @@ class LLVMSourceConfig(object): functionality for adding / removing them. """ - def __init__(self, proj, sourcePath, + def __init__(self, proj, sourcePath, dry, subprojs=LLVMSubproject.get_all_subprojects()): """ Create a source configuration. @@ -83,6 +83,13 @@ class LLVMSourceConfig(object): Temporary project directory (used mostly for logging). sourcePath Must point to a valid LLVM source tree. + dry + Whether or not we are running in dry run mode. If we are, then we do + not try to add or remove any subprojects, but we try to remember + which updates we performed. We don't currently check the subprojects + that are enabled on disk, since for the dry run mode we don't + perform any validation whatsoever on the source directory. This may + change in the future. subprojs : dictionary Dictionary containing a number of LLVMSubproject objects. By default, this contains all the LLVM subprojects as returned by @@ -92,17 +99,22 @@ class LLVMSourceConfig(object): class's methods. It is an error to invoke them with a subproj that does not exist in this dictionary. """ - sourcePath = str(sourcePath) - if not os.path.isdir(sourcePath): - raise EnvironmentError("Invalid path to LLVM source tree") + if not dry: + sourcePath = str(sourcePath) + if not os.path.isdir(sourcePath): + raise EnvironmentError("Invalid path to LLVM source tree") + self.proj = proj + self.llvmSourceTree = Worktree(proj, sourcePath) + else: + self.subprojsEnabledInDryRun = [] - self.proj = proj - self.llvmSourceTree = Worktree(proj, sourcePath) + self.sourcePath = sourcePath + self.dry = dry self.subprojs = subprojs def get_path(self): """Get the path corresponding to this source config.""" - return self.llvmSourceTree.repodir + return self.sourcePath def get_enabled_subprojects(self): """Get a list of the subprojects enabled in this configuration.""" @@ -169,7 +181,7 @@ class LLVMSourceConfig(object): raise RuntimeError("Error while processing {}".format(subproj)) from exc # Visit LLVM last, in case getting the enabled subprojects errors out. - action(self.llvmSourceTree.repodir) + action(self.sourcePath) def for_each_subproj(self, action): """Perform the given action for each subproject excluding LLVM. @@ -196,7 +208,7 @@ class LLVMSourceConfig(object): def __get_subproj_cmake_path(self, subprojName): """Get the full path to subprojName in this source tree.""" subproj = self.__get_subproj_object(subprojName) - return subproj.get_cmake_path(self.llvmSourceTree.repodir) + return subproj.get_cmake_path(self.sourcePath) def __is_enabled(self, subprojName): """ @@ -205,6 +217,9 @@ class LLVMSourceConfig(object): a directory for the subproject exists but does not satisfy those conditions, an EnvironmentError is thrown. """ + if self.dry: + return subprojName in self.subprojsEnabledInDryRun + subprojPath = self.__get_subproj_cmake_path(subprojName) if not os.path.isdir(subprojPath): @@ -239,6 +254,10 @@ class LLVMSourceConfig(object): # Subproject has already been added, nothing to do. return + if self.dry: + self.subprojsEnabledInDryRun.append(subprojName) + return + if os.path.exists(path): raise EnvironmentError( "{} already exists but is not a valid subproject directory." @@ -260,6 +279,11 @@ class LLVMSourceConfig(object): def __remove_subproject(self, subprojName): """Remove a given subproject from this build configuration.""" + if self.dry: + if self.__is_enabled(subprojName): + self.subprojsEnabledInDryRun.remove(subprojName) + return + path = self.__get_subproj_cmake_path(subprojName) if not os.path.isdir(path): diff --git a/scripts/llvm.py b/scripts/llvm.py index cce0ef4..3a4954c 100644 --- a/scripts/llvm.py +++ b/scripts/llvm.py @@ -52,7 +52,7 @@ def projects(args): llvm_worktree_root = args.sources llvm_repos_root = args.repos - config = LLVMSourceConfig(proj, llvm_worktree_root) + config = LLVMSourceConfig(proj, llvm_worktree_root, dry=False) if not args.add and not args.remove: # Nothing to change, just print the current configuration @@ -79,7 +79,7 @@ def push_current_branch(args): proj = Proj() llvm_worktree_root = args.sources - config = LLVMSourceConfig(proj, llvm_worktree_root) + config = LLVMSourceConfig(proj, llvm_worktree_root, dry=False) llvm_worktree = Clone(proj, llvm_worktree_root) local_branch = llvm_worktree.getbranch() @@ -99,7 +99,7 @@ def configure_build(args): proj = Proj() llvm_worktree_root = args.sources - sourceConfig = LLVMSourceConfig(proj, llvm_worktree_root) + sourceConfig = LLVMSourceConfig(proj, llvm_worktree_root, args.dry) buildConfig = LLVMBuildConfig(sourceConfig, args.build) diff --git a/tests/unittests/testllvmsourceconfig.py b/tests/unittests/testllvmsourceconfig.py index 0baf7e3..3bdc4ed 100644 --- a/tests/unittests/testllvmsourceconfig.py +++ b/tests/unittests/testllvmsourceconfig.py @@ -60,7 +60,7 @@ class TestLLVMSourceConfig(unittest.TestCase): def test_get_path(self): sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) self.assertEqual(config.get_path(), sourcePath) def test_detect_enabled_all(self): @@ -76,7 +76,7 @@ class TestLLVMSourceConfig(unittest.TestCase): self.temporaryLLVMbranch) self.assertTrue(os.path.isdir(path), "Failed to create worktree") - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) enabled = config.get_enabled_subprojects() self.assertEqual(set(subprojs), set(enabled), @@ -98,7 +98,7 @@ class TestLLVMSourceConfig(unittest.TestCase): path = os.path.join(sourcePath, "tools", "libcxx") os.makedirs(path) - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) enabled = config.get_enabled_subprojects() self.assertEqual( @@ -120,7 +120,7 @@ class TestLLVMSourceConfig(unittest.TestCase): self.temporaryLLVMbranch) self.assertTrue(os.path.isdir(path), "Failed to create worktree") - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) enabled = config.get_enabled_subprojects() self.assertTrue("lld" in enabled, "Failed to detect lld") @@ -135,7 +135,7 @@ class TestLLVMSourceConfig(unittest.TestCase): path = subprojs["compiler-rt"].get_cmake_path(sourcePath) os.makedirs(path) - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) with self.assertRaises(EnvironmentError) as context: config.get_enabled_subprojects() @@ -157,7 +157,7 @@ class TestLLVMSourceConfig(unittest.TestCase): branch) self.assertTrue(os.path.isdir(path), "Failed to create worktree") - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) with self.assertRaises(EnvironmentError) as context: config.get_enabled_subprojects() @@ -166,7 +166,7 @@ class TestLLVMSourceConfig(unittest.TestCase): self.temporaryLLVMbranch)) def test_add_invalid_subproject(self): - config = LLVMSourceConfig(self.proj, self.temporaryLLVM.repodir) + config = LLVMSourceConfig(self.proj, self.temporaryLLVM.repodir, False) subproj = "not-an-llvm-subproject" subprojPath = self.originalLLVM.repodir # Dummy path @@ -179,7 +179,7 @@ class TestLLVMSourceConfig(unittest.TestCase): def test_add_each_subproject(self): sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) subprojs = LLVMSubproject.get_all_subprojects() for subproj in subprojs: @@ -191,7 +191,7 @@ class TestLLVMSourceConfig(unittest.TestCase): def test_add_all_subprojects(self): sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) to_add = {} subprojs = LLVMSubproject.get_all_subprojects() @@ -209,7 +209,7 @@ class TestLLVMSourceConfig(unittest.TestCase): def test_add_some_subprojects(self): sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) to_add = {} to_add["clang"] = self.__get_subproj_repo("clang") @@ -228,7 +228,7 @@ class TestLLVMSourceConfig(unittest.TestCase): def test_add_existing_subprojects(self): sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) subprojs = LLVMSubproject.get_all_subprojects() existingPath = subprojs["lldb"].get_cmake_path(sourcePath) @@ -253,7 +253,7 @@ class TestLLVMSourceConfig(unittest.TestCase): """ sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) clangRepo = self.__get_subproj_repo("clang") with cd(clangRepo.repodir): @@ -277,7 +277,7 @@ class TestLLVMSourceConfig(unittest.TestCase): sourcePath = self.temporaryLLVM.repodir branch = "different-than-" + self.temporaryLLVMbranch - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) subprojs = LLVMSubproject.get_all_subprojects() existingPath = subprojs["lldb"].get_cmake_path(sourcePath) @@ -303,7 +303,7 @@ class TestLLVMSourceConfig(unittest.TestCase): sourcePath = self.temporaryLLVM.repodir branch = "different-than-" + self.temporaryLLVMbranch - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) subprojs = LLVMSubproject.get_all_subprojects() existingPath = subprojs["lldb"].get_cmake_path(sourcePath) @@ -344,7 +344,7 @@ class TestLLVMSourceConfig(unittest.TestCase): clangPath, self.temporaryLLVMbranch) - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) config.update(remove=["lld"]) self.assertFalse(os.path.isdir(lldPath), "Failed to remove subproject") @@ -363,7 +363,7 @@ class TestLLVMSourceConfig(unittest.TestCase): path, self.temporaryLLVMbranch) - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) config.update(remove=["compiler-rt", "lld"]) for subproj in ["compiler-rt", "lld"]: @@ -390,7 +390,7 @@ class TestLLVMSourceConfig(unittest.TestCase): self.temporaryLLVMbranch) self.assertTrue(os.path.isdir(path), "Failed to create worktree") - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) config.update(remove=list(subprojs.keys())) for subproj in list(subprojs.keys()): @@ -413,7 +413,7 @@ class TestLLVMSourceConfig(unittest.TestCase): self.temporaryLLVMbranch) self.assertTrue(os.path.isdir(path), "Failed to create worktree") - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) for subproj in list(subprojs.keys()): config.update(remove=[subproj]) @@ -437,7 +437,7 @@ class TestLLVMSourceConfig(unittest.TestCase): path, self.temporaryLLVMbranch) - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) config.update(remove=["compiler-rt", "lld", "lld", "compiler-rt"]) for subproj in ["compiler-rt", "lld"]: @@ -452,7 +452,7 @@ class TestLLVMSourceConfig(unittest.TestCase): def test_remove_invalid_subproject(self): sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) subproj = "not-an-llvm-subproject" @@ -476,7 +476,7 @@ class TestLLVMSourceConfig(unittest.TestCase): clangPath = subprojs["clang"].get_cmake_path(sourcePath) - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) config.update(remove=["clang"]) self.assertFalse( @@ -490,7 +490,7 @@ class TestLLVMSourceConfig(unittest.TestCase): subprojs = LLVMSubproject.get_all_subprojects() lldbRepo = self.__get_subproj_repo("lldb") - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) config.update({"lldb" : lldbRepo}) self.assertTrue( @@ -520,7 +520,7 @@ class TestLLVMSourceConfig(unittest.TestCase): path, self.temporaryLLVMbranch) - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) config.update({ "libcxx" : self.__get_subproj_repo("libcxx"), "libcxxabi" : self.__get_subproj_repo("libcxxabi")}, @@ -548,7 +548,7 @@ class TestLLVMSourceConfig(unittest.TestCase): lldRepo = self.__get_subproj_repo("lld") libunwindRepo = self.__get_subproj_repo("libunwind") - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) with self.assertRaises(ValueError) as context: config.update( { "clang" : clangRepo, "lld" : lldRepo, "libunwind" : @@ -574,7 +574,7 @@ class TestLLVMSourceConfig(unittest.TestCase): def test_for_each_enabled(self): sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) logPath = unittest.mock.MagicMock() config.for_each_enabled(logPath) @@ -603,7 +603,7 @@ class TestLLVMSourceConfig(unittest.TestCase): """Test that we rethrow exceptions correctly.""" sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) subprojs = config.subprojs enabled = ["clang", "compiler-rt", "lld", "lldb", "libunwind"] @@ -629,7 +629,7 @@ class TestLLVMSourceConfig(unittest.TestCase): def test_for_each_subproj(self): sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) subprojs = config.subprojs enabled = ["clang", "compiler-rt", "lld", "lldb", "libunwind"] @@ -664,7 +664,7 @@ class TestLLVMSourceConfig(unittest.TestCase): """Test that we rethrow exceptions correctly.""" sourcePath = self.temporaryLLVM.repodir - config = LLVMSourceConfig(self.proj, sourcePath) + config = LLVMSourceConfig(self.proj, sourcePath, False) subprojs = config.subprojs enabled = ["clang", "compiler-rt", "lld", "lldb", "libunwind"] @@ -700,6 +700,100 @@ class TestLLVMSourceConfig(unittest.TestCase): self.assertRegex(str(context.exception.__cause__), "An error has been!!1(.*\n)*") + def test_dry_run_none_enabled(self): + """ + Test that when running in dry run mode, we don't error out if the + source directory is bogus, and also that we report no enabled + subprojects. + """ + sourcePath = "path-to-llvm-source-tree" + + config = LLVMSourceConfig(self.proj, sourcePath, True) + enabled = config.get_enabled_subprojects() + + self.assertEqual([], enabled) + + def test_dry_run_add_subprojects(self): + """ + Test that in dry run mode we don't perform any side effects, but we + remember the subprojects that were added. + """ + sourcePath = "path-to-llvm-source-tree" + + config = LLVMSourceConfig(self.proj, sourcePath, True) + subprojs = config.subprojs + + config.update({"clang" : "path-to-clang-repo", + "compiler-rt" : "path-to-compiler-rt-repo"}) + self.assertFalse( + os.path.isdir(subprojs["clang"].get_cmake_path(sourcePath))) + self.assertFalse( + os.path.isdir(subprojs["compiler-rt"].get_cmake_path(sourcePath))) + + enabled = config.get_enabled_subprojects() + self.assertEqual(set(["clang", "compiler-rt"]), + set(config.get_enabled_subprojects())) + + def test_dry_run_remove_subprojects(self): + """ Test that in dry run mode we don't remove existing subprojects.""" + sourcePath = self.temporaryLLVM.repodir + + subprojs = LLVMSubproject.get_all_subprojects() + enabled = ["clang", "compiler-rt", "lld", "lldb", "libunwind"] + + for subproj in enabled: + path = subprojs[subproj].get_cmake_path(sourcePath) + worktree = Worktree.create( + self.proj, + self.__get_subproj_repo(subproj), + path, + self.temporaryLLVMbranch) + + config = LLVMSourceConfig(self.proj, sourcePath, True) + config.update({}, ["clang", "lld"]) + + for subproj in enabled: + self.assertTrue( + os.path.isdir(subprojs[subproj].get_cmake_path(sourcePath))) + + self.assertNotIn("clang", config.get_enabled_subprojects()) + self.assertNotIn("lld", config.get_enabled_subprojects()) + + def test_dry_run_add_then_remove(self): + """ Test that in dry run mode we correctly keep track of updates.""" + sourcePath = "path-to-llvm-source-tree" + + config = LLVMSourceConfig(self.proj, sourcePath, True) + subprojs = config.subprojs + + config.update({"clang" : "path-to-clang-repo", + "compiler-rt" : "path-to-compiler-rt-repo"}) + enabled = config.get_enabled_subprojects() + self.assertEqual(set(["clang", "compiler-rt"]), + set(config.get_enabled_subprojects())) + + config.update({"lld" : "path-to-lld-repo"}, ["compiler-rt"]) + self.assertEqual(set(["clang", "lld"]), + set(config.get_enabled_subprojects())) + + def test_dry_run_for_each_enabled(self): + """ Test that for_each_enabled works in dry run mode.""" + sourcePath = "path-to-llvm-source-tree" + + config = LLVMSourceConfig(self.proj, sourcePath, True) + subprojs = config.subprojs + + config.update({"clang": "path-to-clang-repo", + "compiler-rt": "path-to-compiler-rt-repo"}) + + action = MagicMock() + config.for_each_enabled(action) + + action.assert_has_calls( + [call(subprojs["clang"].get_cmake_path(sourcePath)), + call(subprojs["compiler-rt"].get_cmake_path(sourcePath))], + any_order=True) + if __name__ == "__main__": unittest.main() |