This is a small tool using Tinyscript to restore permissions under a Git repository (e.g. when a bad backup and restore method messed up with file permissions).
$ pip install pybots tinyscript
$ tsm install git-perm-recovery
This is a small tool using Tinyscript to restore permissions under a Git repository (e.g. when a bad backup and restore method messed up with file permissions).
$ pip install pybots tinyscript
$ tsm install git-perm-recovery
| #!/usr/bin/env python | |
| from tinyscript import * | |
| __author__ = "Alexandre D'Hondt" | |
| __version__ = "1.0" | |
| __copyright__ = ("A. D'Hondt", 2025) | |
| __examples__ = ["", "-r"] | |
| __doc__ = """ | |
| This is a simple tool for restoring permissions under a Git repository | |
| (e.g. when a bad backup and restore method messed up with file permissions). | |
| """ | |
| REGEX = re.compile(r"^ mode change 100(\d+) => 100\d+ (.*)$") | |
| def git_recover_perms(): | |
| """ This will revert permissions back to normal in the current folder. """ | |
| # first, check that the given path is a Git repo | |
| out, err, retc = ts.execute("git diff --summary", returncode=True) | |
| if retc > 0: | |
| err = err.decode().split(".")[0].strip() | |
| if err == "warning: Not a git repository": | |
| raise OSError(f"'{Path.cwd()}' is not a Git repository") | |
| elif err == "fatal: this operation must be run in a work tree": | |
| raise OSError("Not the root of the Git repository") | |
| raise Exception(err) | |
| # then check that it is the root | |
| p, _ = ts.execute("git rev-parse --show-toplevel") | |
| if ts.Path(".").absolute().parts != ts.Path(p.decode().strip()).parts: | |
| raise OSError("Not the root of the Git repository") | |
| # now fix permissions | |
| fixed = False | |
| for line in out.decode().splitlines(): | |
| if (m := REGEX.search(line)): | |
| old_perm, path = m.groups() | |
| ts.Path(path).chmod(int(old_perm, 8)) | |
| fixed = True | |
| return fixed | |
| if __name__ == '__main__': | |
| parser.add_argument("-r", "--recurse", action="store_true", help="recurse for Git repositories from here") | |
| initialize() | |
| try: | |
| ts.execute("git --help") | |
| logger.debug("'git' is installed") | |
| except FileNotFoundError: | |
| logger.critical("'git' is not installed") | |
| sys.exit(1) | |
| cwd = ts.Path.cwd() | |
| for path in (cwd.walk(filter_func=lambda p: p.is_dir()) if args.recurse else [cwd]): | |
| os.chdir(str(path)) | |
| try: | |
| logger.debug(f"fixed permissions for '{path}'") if git_recover_perms() else \ | |
| [logger.warning, logger.debug][args.recurse](f"nothing to change in '{path}'") | |
| except OSError as e: | |
| if not args.recurse: | |
| logger.error(e) | |
| except Exception as e: | |
| logger.error(f"{path}: {e}") | |
| os.chdir(str(cwd)) |