|  | #!/usr/bin/env python | 
|  |  | 
|  | """ | 
|  | Static Analyzer qualification infrastructure: adding a new project to | 
|  | the Repository Directory. | 
|  |  | 
|  | Add a new project for testing: build it and add to the Project Map file. | 
|  | Assumes it's being run from the Repository Directory. | 
|  | The project directory should be added inside the Repository Directory and | 
|  | have the same name as the project ID | 
|  |  | 
|  | The project should use the following files for set up: | 
|  | - cleanup_run_static_analyzer.sh - prepare the build environment. | 
|  | Ex: make clean can be a part of it. | 
|  | - run_static_analyzer.cmd - a list of commands to run through scan-build. | 
|  | Each command should be on a separate line. | 
|  | Choose from: configure, make, xcodebuild | 
|  | - download_project.sh - download the project into the CachedSource/ | 
|  | directory. For example, download a zip of | 
|  | the project source from GitHub, unzip it, | 
|  | and rename the unzipped directory to | 
|  | 'CachedSource'. This script is not called | 
|  | when 'CachedSource' is already present, | 
|  | so an alternative is to check the | 
|  | 'CachedSource' directory into the | 
|  | repository directly. | 
|  | - CachedSource/ - An optional directory containing the source of the | 
|  | project being analyzed. If present, | 
|  | download_project.sh will not be called. | 
|  | - changes_for_analyzer.patch - An optional patch file for any local | 
|  | changes | 
|  | (e.g., to adapt to newer version of clang) | 
|  | that should be applied to CachedSource | 
|  | before analysis. To construct this patch, | 
|  | run the download script to download | 
|  | the project to CachedSource, copy the | 
|  | CachedSource to another directory (for | 
|  | example, PatchedSource) and make any | 
|  | needed modifications to the copied | 
|  | source. | 
|  | Then run: | 
|  | diff -ur CachedSource PatchedSource \ | 
|  | > changes_for_analyzer.patch | 
|  | """ | 
|  | import SATestBuild | 
|  | from ProjectMap import ProjectMap, ProjectInfo | 
|  |  | 
|  | import os | 
|  | import sys | 
|  |  | 
|  |  | 
|  | def add_new_project(project: ProjectInfo): | 
|  | """ | 
|  | Add a new project for testing: build it and add to the Project Map file. | 
|  | :param name: is a short string used to identify a project. | 
|  | """ | 
|  |  | 
|  | test_info = SATestBuild.TestInfo(project, is_reference_build=True) | 
|  | tester = SATestBuild.ProjectTester(test_info) | 
|  |  | 
|  | project_dir = tester.get_project_dir() | 
|  | if not os.path.exists(project_dir): | 
|  | print(f"Error: Project directory is missing: {project_dir}") | 
|  | sys.exit(-1) | 
|  |  | 
|  | # Build the project. | 
|  | tester.test() | 
|  |  | 
|  | # Add the project name to the project map. | 
|  | project_map = ProjectMap(should_exist=False) | 
|  |  | 
|  | if is_existing_project(project_map, project): | 
|  | print( | 
|  | f"Warning: Project with name '{project.name}' already exists.", | 
|  | file=sys.stdout, | 
|  | ) | 
|  | print("Reference output has been regenerated.", file=sys.stdout) | 
|  | else: | 
|  | project_map.projects.append(project) | 
|  | project_map.save() | 
|  |  | 
|  |  | 
|  | def is_existing_project(project_map: ProjectMap, project: ProjectInfo) -> bool: | 
|  | return any( | 
|  | existing_project.name == project.name | 
|  | for existing_project in project_map.projects | 
|  | ) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | print("SATestAdd.py should not be used on its own.") | 
|  | print("Please use 'SATest.py add' instead") | 
|  | sys.exit(1) |