Skip to content

Commit 9e19934

Browse files
committed
Fix permissions when openrsync is used
1 parent bb2e7ef commit 9e19934

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

apple/internal/templates/apple_device.template.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,12 +300,22 @@ def extracted_app(
300300
# fail with `Unhandled error domain NSPOSIXErrorDomain, code 13`.
301301
dst_dir = os.path.join(tempfile.gettempdir(), "bazel_temp_" + app_name)
302302
os.makedirs(dst_dir, exist_ok=True)
303+
file_mode = "u+w"
304+
# Mitigate any previous runs of openrsync that synced the application
305+
# into dst_dir without applying the correct permissions.
306+
dst_dir_application = os.path.join(
307+
dst_dir, os.path.basename(application_output_path)
308+
)
309+
if (os.path.exists(dst_dir_application)
310+
and not os.access(dst_dir_application, os.W_OK)):
311+
fix_permissions(dst_dir, file_mode)
303312
rsync_command = [
304313
"/usr/bin/rsync",
305314
"--archive",
306315
"--delete",
307316
"--checksum",
308-
"--chmod=u+w",
317+
"--perms",
318+
f"--chmod={file_mode}",
309319
"--verbose",
310320
# The output path might itself be a symlink; resolve to the
311321
# real path so rsync doesn't just copy the symlink.
@@ -325,6 +335,7 @@ def extracted_app(
325335
text=True,
326336
)
327337
logger.debug("rsync output: %s", result.stdout)
338+
fix_permissions(dst_dir, file_mode)
328339
yield os.path.join(dst_dir, app_name + ".app")
329340
else:
330341
# Create a new temporary directory for each run, deleting it
@@ -417,6 +428,27 @@ def run_app(
417428
subprocess.run(args, env=devicectl_launch_environ(), check=False)
418429

419430

431+
def fix_permissions(
432+
directory: str,
433+
mode: str
434+
):
435+
# Fix permissions on macOS 15.4+ until openrsync correctly applies the file permissions
436+
# passed via --chmod.
437+
version = platform.platform(terse=True).removeprefix("macOS-")
438+
version_components = version.split(".")
439+
major = int(version_components[0])
440+
minor = int(version_components[1])
441+
if major < 15:
442+
return
443+
if minor < 4:
444+
return
445+
logger.debug("Fix permissions")
446+
result = subprocess.run(
447+
["/usr/bin/find", directory, "-exec", "chmod", mode, "{}", ";"],
448+
check=True,
449+
)
450+
451+
420452
def main(
421453
*,
422454
app_name: str,

apple/internal/templates/apple_simulator.template.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,12 +537,22 @@ def extracted_app(
537537
# fail with `Unhandled error domain NSPOSIXErrorDomain, code 13`.
538538
dst_dir = os.path.join(tempfile.gettempdir(), "bazel_temp_" + app_name)
539539
os.makedirs(dst_dir, exist_ok=True)
540+
file_mode = "u+w"
541+
# Mitigate any previous runs of openrsync that synced the application
542+
# into dst_dir without applying the correct permissions.
543+
dst_dir_application = os.path.join(
544+
dst_dir, os.path.basename(application_output_path)
545+
)
546+
if (os.path.exists(dst_dir_application)
547+
and not os.access(dst_dir_application, os.W_OK)):
548+
fix_permissions(dst_dir, file_mode)
540549
rsync_command = [
541550
"/usr/bin/rsync",
542551
"--archive",
543552
"--delete",
544553
"--checksum",
545-
"--chmod=u+w",
554+
"--perms",
555+
f"--chmod={file_mode}",
546556
"--verbose",
547557
# The output path might itself be a symlink; resolve to the
548558
# real path so rsync doesn't just copy the symlink.
@@ -562,6 +572,7 @@ def extracted_app(
562572
text=True,
563573
)
564574
logger.debug("rsync output: %s", result.stdout)
575+
fix_permissions(dst_dir, file_mode)
565576
yield os.path.join(dst_dir, app_name + ".app")
566577
else:
567578
# Create a new temporary directory for each run, deleting it
@@ -689,6 +700,27 @@ def run_app_in_simulator(
689700
subprocess.run(args, env=simctl_launch_environ(), check=False)
690701

691702

703+
def fix_permissions(
704+
directory: str,
705+
mode: str
706+
):
707+
# Fix permissions on macOS 15.4+ until openrsync correctly applies the file permissions
708+
# passed via --chmod.
709+
version = platform.platform(terse=True).removeprefix("macOS-")
710+
version_components = version.split(".")
711+
major = int(version_components[0])
712+
minor = int(version_components[1])
713+
if major < 15:
714+
return
715+
if minor < 4:
716+
return
717+
logger.debug("Fix permissions")
718+
result = subprocess.run(
719+
["/usr/bin/find", directory, "-exec", "chmod", mode, "{}", ";"],
720+
check=True,
721+
)
722+
723+
692724
def main(
693725
*,
694726
app_name: str,

0 commit comments

Comments
 (0)