Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make_tree_writable: handle junctions and add tests #107

Merged
merged 1 commit into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions msys2_autobuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,24 +122,36 @@ def shlex_join(split_command: Sequence[str]) -> str:
check_call([executable, '-lc'] + [shlex_join([str(a) for a in args])], env=env, **kwargs)


def make_tree_writable(topdir: PathLike) -> None:
# Ensure all files and directories under topdir are writable
# (and readable) by owner.
# Taken from meson, and adjusted

def chmod(p: PathLike) -> None:
print(p)
lazka marked this conversation as resolved.
Show resolved Hide resolved
os.chmod(p, os.stat(p).st_mode | stat.S_IWRITE | stat.S_IREAD)

chmod(topdir)
for root, dirs, files in os.walk(topdir):
for d in dirs:
chmod(os.path.join(root, d))
# Work around Python bug following junctions
# https://github.com/python/cpython/issues/67596#issuecomment-1918112817
if hasattr(os.path, 'isjunction'): # Python 3.12 only
dirs[:] = [d for d in dirs if not os.path.isjunction(os.path.join(root, d))]
for fname in files:
fpath = os.path.join(root, fname)
if os.path.isfile(fpath):
chmod(fpath)


def reset_git_repo(path: PathLike):

def clean():
assert os.path.exists(path)
check_call(["git", "clean", "-xfdf"], cwd=path)
check_call(["git", "reset", "--hard", "HEAD"], cwd=path)

def make_tree_writable(topdir: PathLike) -> None:
# Ensure all files and directories under topdir are writable
# (and readable) by owner.
# Taken from meson
for d, _, files in os.walk(topdir):
os.chmod(d, os.stat(d).st_mode | stat.S_IWRITE | stat.S_IREAD)
for fname in files:
fpath = os.path.join(d, fname)
if os.path.isfile(fpath):
os.chmod(fpath, os.stat(fpath).st_mode | stat.S_IWRITE | stat.S_IREAD)

made_writable = False
for i in range(10):
try:
Expand Down
33 changes: 33 additions & 0 deletions tests/main_test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,40 @@
# type: ignore

import os
import stat
import tempfile
from pathlib import Path

from msys2_autobuild.utils import parse_optional_deps
from msys2_autobuild.queue import parse_buildqueue, get_cycles
from msys2_autobuild.build import make_tree_writable


def test_make_tree_writable():
with tempfile.TemporaryDirectory() as tempdir:
nested_dir = Path(tempdir) / "nested"
nested_junction = nested_dir / "junction"
nested_dir.mkdir()
file_path = nested_dir / "test_file.txt"
file_path.write_text("content")

# Create a junction loop if possible, to make sure we ignore it
if hasattr(os.path, 'isjunction') and os.name == 'nt':
import _winapi
_winapi.CreateJunction(str(nested_dir), str(nested_junction))
else:
nested_junction.mkdir()

# Remove permissions
for p in [tempdir, nested_dir, file_path, nested_junction]:
os.chmod(p, os.stat(p).st_mode & ~stat.S_IWRITE & ~stat.S_IREAD)

make_tree_writable(tempdir)

assert os.access(tempdir, os.W_OK) and os.access(tempdir, os.R_OK)
assert os.access(nested_dir, os.W_OK) and os.access(nested_dir, os.R_OK)
assert os.access(file_path, os.W_OK) and os.access(file_path, os.R_OK)
assert os.access(nested_junction, os.W_OK) and os.access(nested_junction, os.R_OK)


def test_parse_optional_deps():
Expand Down