blob: 84c2236e60227e5c352b86df8e4d40b4c01f542a [file] [log] [blame]
# Copyright 2022 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recursively unmount directory trees.
This is a convenience command for developers to quickly tear down & clean up
whatever random paths they have.
"""
import logging
from pathlib import Path
from chromite.cli import command
from chromite.lib import osutils
class UnmountCommandBase(command.CliCommand):
"""Recursively unmount directory trees.
Base class for unmount & umount alias commands.
"""
@classmethod
def AddParser(cls, parser) -> None:
"""Add parser arguments."""
super().AddParser(parser)
parser.add_argument(
"--cleanup",
action="store_true",
help="Trim empty mount dirs",
)
parser.add_argument(
"--lazy", action="store_true", help="Perform a lazy unmount"
)
# NB: We don't use type='path' in order to handle symlinks directly.
parser.add_argument(
"paths", nargs="+", help="Base directory to cleanup"
)
@classmethod
def ProcessOptions(cls, parser, options) -> None:
"""Post process options."""
options.paths = [Path(x).expanduser() for x in options.paths]
def Run(self) -> None:
"""Perform the cros mount command."""
for path in self.options.paths:
if not path.exists():
# Funky edge case: ignore broken symlinks. We use these when
# mounting to provide dir_<partition number> and dir_<label>.
if path.is_symlink():
if self.options.cleanup:
path.unlink()
continue
logging.warning("%s: directory does not exist", path)
continue
logging.info("Unmounting %s recursively", path)
osutils.UmountTree(
path, lazy=self.options.lazy, cleanup=self.options.cleanup
)
@command.command_decorator("unmount")
class UnmountCommand(UnmountCommandBase):
"""Recursively unmount directory trees."""