106 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python3
 | |
| """Uninstall a previously installed CMake installation.
 | |
| 
 | |
| Read the ``install_manifest.txt`` file from a CMake build directory
 | |
| which has been installed then delete the files, and optionally the empty
 | |
| subdirectories of the install prefix, specified within.
 | |
| """
 | |
| 
 | |
| from argparse import ArgumentParser, RawDescriptionHelpFormatter
 | |
| from os import listdir, path, remove, rmdir
 | |
| from sys import stderr
 | |
| 
 | |
| 
 | |
| def uninstall(build_dir, recursive=False):
 | |
|     """Uninstall a previoulsy installed CMake installation.
 | |
| 
 | |
|     Arguments:
 | |
|         :build_dir: Path to the build directory containing the
 | |
|         ``install_manifest.txt`` of files to uninstall.
 | |
|         :recursive: Boolean flag to enable recursively uninstall empty
 | |
|         directories up to the install prefix specified in ``CMakeCache.txt``.
 | |
|     """
 | |
|     # Get the list of installed files from the install_manifest.txt
 | |
|     install_manifest_path = path.join(build_dir, 'install_manifest.txt')
 | |
|     with open(install_manifest_path, 'r') as install_manifest_file:
 | |
|         install_manifest = sorted(install_manifest_file.read().splitlines())
 | |
|     # Delete files from the filesystem
 | |
|     removed = []
 | |
|     directories = []
 | |
|     for entry in install_manifest:
 | |
|         directories.append(path.dirname(entry))
 | |
|         if path.isfile(entry):
 | |
|             remove(entry)
 | |
|             removed.append(entry)
 | |
|     if recursive:
 | |
|         # Get the install prefix from CMakeCache.txt
 | |
|         cmakecache_path = path.join(build_dir, 'CMakeCache.txt')
 | |
|         with open(cmakecache_path, 'r') as cmakecache_file:
 | |
|             for line in cmakecache_file.read().splitlines():
 | |
|                 if line.startswith('CMAKE_INSTALL_PREFIX'):
 | |
|                     prefix = path.normpath(line.split('=')[1])
 | |
|                     break
 | |
|         while True:
 | |
|             # Remove duplicates from list
 | |
|             directories = list(dict.fromkeys(directories))
 | |
|             # Find directories in list which are not empty
 | |
|             not_empty = []
 | |
|             for index, entry in enumerate(directories):
 | |
|                 if listdir(entry):
 | |
|                     not_empty.append(index)
 | |
|             # Remove directories which are not empty from list
 | |
|             for index in reversed(not_empty):
 | |
|                 del directories[index]
 | |
|             # Delete directories from the filesystem
 | |
|             to_del = []
 | |
|             to_append = []
 | |
|             for index, entry in enumerate(directories):
 | |
|                 rmdir(entry)
 | |
|                 removed.append(entry)
 | |
|                 to_del.append(index)
 | |
|                 parent = path.dirname(entry)
 | |
|                 # Add parent directory to the list when not the install prefix
 | |
|                 if path.normpath(parent) != prefix:
 | |
|                     to_append.append(parent)
 | |
|             # Remove deleted directories from list
 | |
|             for index in reversed(to_del):
 | |
|                 del directories[index]
 | |
|             directories += to_append
 | |
|             # Exit loop when no more directories in list
 | |
|             if not directories:
 | |
|                 break
 | |
|     return removed
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     """Command line entry point."""
 | |
|     cli = ArgumentParser(description=__doc__,
 | |
|                          formatter_class=RawDescriptionHelpFormatter)
 | |
|     cli.add_argument('--version', action='version', version='%(prog)s 0.1.0')
 | |
|     cli.add_argument('-q',
 | |
|                      '--quiet',
 | |
|                      action='store_true',
 | |
|                      help="don't print removed entries to stdout")
 | |
|     cli.add_argument('-r',
 | |
|                      '--recursive',
 | |
|                      action='store_true',
 | |
|                      help='recursively remove empty directories')
 | |
|     cli.add_argument('build_dir',
 | |
|                      help='path to the installed CMake build directory')
 | |
|     args = cli.parse_args()
 | |
|     try:
 | |
|         removed = uninstall(args.build_dir, recursive=args.recursive)
 | |
|         if not args.quiet:
 | |
|             for entry in removed:
 | |
|                 print(f'-- Uninstalling: {entry}')
 | |
|     except FileNotFoundError as error:
 | |
|         print(f'error: file not found: {error.filename}', file=stderr)
 | |
|         exit(1)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     try:
 | |
|         main()
 | |
|     except KeyboardInterrupt:
 | |
|         exit(130)
 |