Skip to content
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"macos:build": "nu scripts/macos/build.nu",
"macos:check": "nu scripts/macos/check.nu",
"macos:doctor": "nu scripts/macos/doctor.nu",
"macos:install": "nu scripts/macos/install.nu",
"macos:release": "nu scripts/macos/release.nu",
"macos:run": "nu scripts/macos/run.nu"
},
Expand Down
1 change: 1 addition & 0 deletions packages/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ opentelemetry_sdk = { workspace = true }
indexmap = { workspace = true }
indoc = { workspace = true }
libc = { workspace = true }
liblzma = { workspace = true }
maml = { workspace = true }
miette = { workspace = true }
num = { workspace = true }
Expand Down
53 changes: 45 additions & 8 deletions packages/cli/test.nu
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ def main [
# Build and install the current macOS app and file system extension. Isolate
# its default-feature Cargo build from the all-features test binary.
if $fskit {
force_unmount_vfs (fskit_temp_root)
stop_fskit_provider $release
let build_args = if $release { ['--release'] } else { [] }
let cargo_target_dir = ($repository_path | path join 'target/macos')
^bun run macos:build --cargo-target-dir $cargo_target_dir ...$build_args
Expand Down Expand Up @@ -923,12 +925,15 @@ export def --env spawn [
--quickjs # Use QuickJS as the JS engine.
--url (-u): string
] {
# Give the object store's lock semaphores a unique prefix per server. lmdb
# appends 'r' and 'w' to form the two POSIX semaphore names, which are global
# to the machine, so concurrent test servers must not share a prefix. The
# prefix plus one character must fit the platform limit, which is 31
# characters on macOS.
let object_store_posix_sem_prefix = $'/tg-((random chars) | str lowercase | str substring 0..7)'
let use_fskit = (($env.TANGRAM_TEST_FSKIT? | default "") | str length) > 0

# Use unique semaphore names in the namespace FSKit can access.
let object_store_posix_sem_prefix = if $use_fskit {
let app_group_identifier = (identifiers).app_group_identifier
$'($app_group_identifier)/((random chars) | str lowercase | str substring 0..5)'
} else {
$'/tg-((random chars) | str lowercase | str substring 0..7)'
}

mut default_config = {
advanced: {
Expand Down Expand Up @@ -978,7 +983,6 @@ export def --env spawn [
}
}

let use_fskit = (($env.TANGRAM_TEST_FSKIT? | default "") | str length) > 0
if $use_fskit {
$default_config = $default_config | merge deep {
vfs: {
Expand Down Expand Up @@ -1198,7 +1202,11 @@ export def --env spawn [
rm -rf $path
}

{ config: $config_path, directory: $directory_path, url: $url }
let vfs = $config | get --optional vfs
let cache_directory_name = if $vfs == null or $vfs == false { 'artifacts' } else { 'cache' }
let cache_directory = $directory_path | path join $cache_directory_name

{ cache_directory: $cache_directory, config: $config_path, directory: $directory_path, url: $url }
}

def clean_databases [id: string] {
Expand Down Expand Up @@ -1674,6 +1682,35 @@ def force_unmount_vfs_macos [path: string] {
}
}

def stop_fskit_provider [release: bool] {
let app_name = if $release { 'Tangram' } else { 'Tangram Dev' }
let executable = (
$env.HOME
| path join $'Applications/($app_name).app/Contents/Extensions/TangramFSKit.appex/Contents/MacOS/TangramFSKit'
)
let pids = fskit_provider_pids $executable
for pid in $pids {
try { kill --quiet $pid }
}
for _ in 1..100 {
if (fskit_provider_pids $executable | is-empty) {
return
}
sleep 50ms
}
for pid in (fskit_provider_pids $executable) {
try { kill --force --quiet $pid }
}
}

def fskit_provider_pids [executable: path] {
ps --long
| where { |process|
($process.command? | default '') | str starts-with $executable
}
| get pid
}

def force_unmount_vfs_linux [path: string] {
let mounted_artifacts_paths = (
try {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/tests/cache/branch_directory.nu
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ let id = tg checkin $path
tg cache $id

# Snapshot the artifacts directory.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
2 changes: 1 addition & 1 deletion packages/cli/tests/cache/directory.nu
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ let id = tg put $artifact

let output = tg cache $id

snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
6 changes: 3 additions & 3 deletions packages/cli/tests/cache/directory_containing_file_cycle.nu
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ let path = artifact {
'#
}
let id = tg build --no-cache-pointers $path
rm --recursive --force ($server.directory | path join "artifacts")
mkdir ($server.directory | path join "artifacts")
rm --recursive --force $server.cache_directory
mkdir $server.cache_directory

# Cache.
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ let path = artifact {
'#
}
let id = tg build --no-cache-pointers $path
rm --recursive --force ($server.directory | path join "artifacts")
mkdir ($server.directory | path join "artifacts")
rm --recursive --force $server.cache_directory
mkdir $server.cache_directory

# Cache.
tg cache $id

snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
2 changes: 1 addition & 1 deletion packages/cli/tests/cache/directory_with_symlink.nu
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
6 changes: 3 additions & 3 deletions packages/cli/tests/cache/directory_with_symlink_cycle.nu
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ let artifact = artifact {
}
let id = tg checkin --no-cache-pointers $artifact
let id = tg build $id
rm --recursive --force ($server.directory | path join "artifacts")
mkdir ($server.directory | path join "artifacts")
rm --recursive --force $server.cache_directory
mkdir $server.cache_directory

# Cache.
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ let path = artifact {
'#
}
let id = tg build --no-cache-pointers $path
rm --recursive --force ($server.directory | path join "artifacts")
mkdir ($server.directory | path join "artifacts")
rm --recursive --force $server.cache_directory
mkdir $server.cache_directory

tg cache $id | complete

snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
2 changes: 1 addition & 1 deletion packages/cli/tests/cache/executable_file.nu
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
2 changes: 1 addition & 1 deletion packages/cli/tests/cache/file.nu
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
6 changes: 3 additions & 3 deletions packages/cli/tests/cache/file_cycle.nu
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ let path = artifact {
'#
}
let id = tg build --no-cache-pointers $path
rm --recursive --force ($server.directory | path join "artifacts")
mkdir ($server.directory | path join "artifacts")
rm --recursive --force $server.cache_directory
mkdir $server.cache_directory

# Cache.
let output = tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
2 changes: 1 addition & 1 deletion packages/cli/tests/cache/file_with_dependency.nu
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
6 changes: 3 additions & 3 deletions packages/cli/tests/cache/graph_directory.nu
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ let artifact = artifact {
}
let id = tg checkin --no-cache-pointers $artifact
let id = tg build $id
rm --recursive --force ($server.directory | path join "artifacts")
mkdir ($server.directory | path join "artifacts")
rm --recursive --force $server.cache_directory
mkdir $server.cache_directory

# Cache.
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
2 changes: 1 addition & 1 deletion packages/cli/tests/cache/graph_file.nu
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
2 changes: 1 addition & 1 deletion packages/cli/tests/cache/graph_symlink.nu
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts") '
snapshot --path $server.cache_directory '
{
"kind": "directory",
"entries": {
Expand Down
6 changes: 3 additions & 3 deletions packages/cli/tests/cache/reference_to_cycle.nu
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ let artifact = artifact {
'
}
let id = tg build --no-cache-pointers $artifact
rm --recursive --force ($server.directory | path join "artifacts")
mkdir ($server.directory | path join "artifacts")
rm --recursive --force $server.cache_directory
mkdir $server.cache_directory

let output = tg cache $id

snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
2 changes: 1 addition & 1 deletion packages/cli/tests/cache/symlink.nu
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ let id = tg put $artifact
tg cache $id

# Snapshot.
snapshot --path ($server.directory | path join "artifacts")
snapshot --path $server.cache_directory
4 changes: 4 additions & 0 deletions packages/macos/Tangram/Resources/TangramHelper.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
</dict>
Expand Down
52 changes: 44 additions & 8 deletions packages/macos/TangramFSKit/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,8 @@ final class TangramVolume: FSVolume, FSVolume.Operations, FSVolume.OpenCloseOper
let objectStoreMapSize = options["object_store_map_size"].flatMap(UInt64.init) ?? 0
let objectStorePath = options["object_store_path"] ?? ""

// The object store's lock semaphores must be named so that the sandboxed
// extension and the server can both open them. When the server does not
// send a prefix, default to the app group identifier, which the sandbox
// permits both processes to open. LMDB appends an 'r' or 'w' character.
let objectStorePosixSemPrefix = options["object_store_posix_sem_prefix"] ?? appGroupIdentifier
// Share the LMDB lock through the app group.
let objectStorePosixSemPrefix = options["object_store_posix_sem_prefix"] ?? "\(appGroupIdentifier)/lmdb"

// The client connects to the server over the unix socket the server sends as
// a mount option, which lets concurrent servers each serve on their own
Expand Down Expand Up @@ -654,6 +651,10 @@ final class TangramVolume: FSVolume, FSVolume.Operations, FSVolume.OpenCloseOper
reply(nil)
return
}
if item.handle != nil {
reply(nil)
return
}
submit({ response, status in
var handle: UInt64 = 0
guard let response, tg_response_open(response, &handle, nil) == 0 else {
Expand All @@ -668,7 +669,7 @@ final class TangramVolume: FSVolume, FSVolume.Operations, FSVolume.OpenCloseOper
}

func closeItem(_ item: FSItem, modes: FSVolume.OpenModes, replyHandler reply: @escaping (Error?) -> Void) {
if let item = item as? TangramItem, let handle = item.handle {
if modes.isEmpty, let item = item as? TangramItem, let handle = item.handle {
_ = self.withProvider { tg_provider_close_sync($0, handle) }
item.handle = nil
}
Expand All @@ -682,15 +683,50 @@ final class TangramVolume: FSVolume, FSVolume.Operations, FSVolume.OpenCloseOper
into buffer: FSMutableFileDataBuffer,
replyHandler reply: @escaping (Int, Error?) -> Void,
) {
guard let item = item as? TangramItem, let handle = item.handle else {
reply(0, posixError(EBADF))
guard let item = item as? TangramItem else {
reply(0, posixError(EINVAL))
return
}
guard offset >= 0 else {
reply(0, posixError(EINVAL))
return
}
if let handle = item.handle {
read(handle: handle, offset: offset, length: length, into: buffer, closeAfterRead: false, replyHandler: reply)
return
}
// FSKit can read an executable before opening it.
submit({ response, status in
var handle: UInt64 = 0
guard let response, tg_response_open(response, &handle, nil) == 0 else {
reply(0, posixError(status < 0 ? -status : EIO))
return
}
self.read(
handle: handle,
offset: offset,
length: length,
into: buffer,
closeAfterRead: true,
replyHandler: reply,
)
}, { callback, context in
self.withProvider { tg_provider_open_async($0, item.nodeID, callback, context) }
})
}

private func read(
handle: UInt64,
offset: off_t,
length: Int,
into buffer: FSMutableFileDataBuffer,
closeAfterRead: Bool,
replyHandler reply: @escaping (Int, Error?) -> Void,
) {
submit({ response, status in
if closeAfterRead {
_ = self.withProvider { tg_provider_close_sync($0, handle) }
}
var pointer: UnsafePointer<UInt8>?
var count = 0
guard let response, tg_response_bytes(response, &pointer, &count) == 0, let pointer else {
Expand Down
1 change: 1 addition & 0 deletions packages/sandbox/src/seatbelt/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ fn create_sandbox_profile(arg: &crate::Arg) -> tg::Result<CString> {
(deny default)

;; Allow most system operations.
(allow dynamic-code-generation)
(allow syscall*)
(allow system-socket)
(allow mach*)
Expand Down
Loading