Repository: vercel/next.js
File: crates/napi/src/lockfile.rs (Rust)

Code before:
                    LockfileInner { file },
                ))))))
            }
            Err(err)
                if err.raw_os_error()
                    == Some(Foundation::ERROR_SHARING_VIOLATION.try_into().unwrap()) =>
            {
                Ok(None)
            }
            Err(err) => Err(err.into()),
        }
    };

    #[cfg(not(windows))]
    return {
        use std::fs::TryLockError;

        let file = open_options.open(&path)?;
        match file.try_lock() {
            Ok(_) => {
                // Write content to the lockfile if provided
                if let Some(ref data) = content {
                    // Need to get a mutable reference
                    let mut file_ref = &file;
                    let _ = file_ref.write_all(data.as_bytes());
                    let _ = file_ref.flush();
                }
                Ok(Some(External::new(Mutex::new(ManuallyDrop::new(Some(
                    LockfileInner {
                        file,
                        path: path.into(),
                    },
                ))))))
            }
            Err(TryLockError::WouldBlock) => Ok(None),
            Err(TryLockError::Error(err)) => Err(err.into()),
        }
    };
}

#[napi(ts_return_type = "Promise<{ __napiType: \"Lockfile\" } | null>")]
pub async fn lockfile_try_acquire(
    path: String,
    content: Option<String>,
) -> napi::Result<Option<External<JsLockfile>>> {
    tokio::task::spawn_blocking(move || lockfile_try_acquire_sync(path, content))
        .await
        .context("panicked while attempting to acquire lockfile")?
}

/// Read the content of a lockfile without acquiring it.

Review comment (suggestion):
I'm guessing this is AI, because that's not how you'd get a mutable reference, that'd be `&mut file`.

But method calls automatically create references: https://doc.rust-lang.org/reference/expressions/method-call-expr.html#r-expr.method.candidate-receivers-refs

```suggestion
                    file.write_all(data.as_bytes())?;
                    file.flush()?;
```

Code after:
                Ok(Some(External::new(Mutex::new(ManuallyDrop::new(Some(
                    LockfileInner { file },
                ))))))
            }
            Err(err)
                if err.raw_os_error()
                    == Some(Foundation::ERROR_SHARING_VIOLATION.try_into().unwrap()) =>
            {
                Ok(None)
            }
            Err(err) => Err(err.into()),
        }
    };

    #[cfg(not(windows))]
    return {
        use std::{fs::TryLockError, io::Seek};

        // On Unix, we must NOT truncate on open because flock is advisory -
        // opening with truncate would clear another process's lockfile content.
        // Instead, open without truncate, acquire the lock, then truncate.
        let mut open_options = OpenOptions::new();
        open_options.write(true).create(true).read(true);

        let file = open_options.open(&path)?;
        match file.try_lock() {
            Ok(_) => {
                // We have the lock - now truncate and write content
                file.set_len(0)?;
                (&file).seek(std::io::SeekFrom::Start(0))?;
                if let Some(ref data) = content {
                    (&file).write_all(data.as_bytes())?;
                    (&file).flush()?;
                }
                Ok(Some(External::new(Mutex::new(ManuallyDrop::new(Some(
                    LockfileInner {
                        file,
                        path: path.into(),
                    },
                ))))))
            }
            Err(TryLockError::WouldBlock) => Ok(None),
            Err(TryLockError::Error(err)) => Err(err.into()),
        }
    };
}

#[napi(ts_return_type = "Promise<{ __napiType: \"Lockfile\" } | null>")]
pub async fn lockfile_try_acquire(
    path: String,
    content: Option<String>,