Skip to content

Conversation

@Parsifa1
Copy link
Contributor

@Parsifa1 Parsifa1 commented Oct 3, 2025

Sanity Checking

  • I have updated the changelog as per my changes
  • I have tested, and self-reviewed my code
  • Style and consistency
    • I ran nix fmt to format my Nix code
    • I ran cargo fmt to format my Rust code
    • I have added appropriate documentation to new code
    • My changes are consistent with the rest of the codebase
  • Correctness
    • I ran cargo clippy and fixed any new linter warnings.
  • If new changes are particularly complex:
    • My code includes comments in particularly complex areas to explain the
      logic
    • I have documented the motive for those changes in the PR body or commit
      description.
  • Tested on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin

close #314

Add a 👍 reaction to pull requests you find important.

Summary by CodeRabbit

  • New Features
    • Improved elevation flow: sudo now optionally propagates askpass and passes environment more reliably to reduce interactive prompt issues.
  • Bug Fixes
    • macOS: elevated commands no longer inherit HOME (non-elevated commands keep HOME) to avoid permission/path issues.
    • More consistent assembly of elevated commands for reliable cross-platform execution.
  • Chores
    • Dependency entry reordered with no user-facing impact.
  • Tests
    • Updated tests to reflect macOS HOME semantics and new elevation behavior.

@coderabbitai
Copy link

coderabbitai bot commented Oct 3, 2025

Walkthrough

Adds a private Command::build_sudo_parts helper and refactors elevated command assembly to combine sudo parts with the current executable and args; macOS-elevation sets HOME="" in env_vars while non-elevated commands preserve HOME; tests and minor docs updated. Cargo.toml reordered yansi.

Changes

Cohort / File(s) Summary
Command execution & elevation
src/commands.rs
Adds private build_sudo_parts(&self) -> Result<Vec<String>>; refactors self_elevate_cmd and run flow to assemble elevated commands by concatenating sudo parts + current executable + args; propagates NH_SUDO_ASKPASS via -A when present; macOS-specific behavior: when elevation requested set HOME to "" in env_vars; non-elevated commands continue to propagate HOME; updated inline comments and tests to match new semantics.
Dependency manifest
Cargo.toml
Reordered yansi entry within [dependencies] (no functional change).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant User
  participant nh
  participant Cmd as Command
  participant Sudo as sudo
  participant Exec as current_executable

  User->>nh: invoke nh (may require elevation)
  nh->>Cmd: needs_elevation?
  alt elevation required
    nh->>Cmd: build_sudo_parts(NH_SUDO_ASKPASS?)
    note right of Cmd #DDDDFF: returns sudo parts (e.g. ["sudo","-A"?, "--preserve-env","--","env",...])
    nh->>Sudo: exec sudo parts
    opt NH_SUDO_ASKPASS present
      Sudo->>Sudo: include `-A` and ensure NH_SUDO_ASKPASS in env
    end
    Sudo->>Exec: exec current_executable with args and prepared env
  else not elevated
    nh->>Exec: exec current_executable with args and inherited env
  end
Loading
sequenceDiagram
  autonumber
  participant nh
  participant OS

  nh->>OS: detect target_os
  alt macOS and elevation requested
    nh->>nh: set HOME = ""
  else non-macOS or not elevated
    nh->>nh: propagate HOME from environment (if present)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The reordering of the yansi dependency in Cargo.toml is unrelated to fixing the $HOME warning and the macOS elevation logic, introducing an out‐of‐scope change that does not impact the issue’s objectives. Please remove the yansi dependency reordering from Cargo.toml to keep the changeset focused solely on the macOS HOME warning fix.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “darwin: fix "$HOME is not owned by you" warning” clearly summarizes the main change by specifying the affected platform and the specific warning being addressed, matching the pull request’s macOS‐focused fix.
Linked Issues Check ✅ Passed The pull request implements macOS‐specific logic to clear HOME when elevating commands, refactors the sudo command build path, and updates tests to validate these changes, directly resolving the recurring “$HOME is not owned by you” warning described in issue #314.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@NotAShelf NotAShelf changed the title fix: "$HOME is not owned by you" on darwin darwin: fix "$HOME is not owned by you" error Oct 3, 2025
@NotAShelf NotAShelf changed the title darwin: fix "$HOME is not owned by you" error darwin: fix "$HOME is not owned by you" warning Oct 3, 2025
@Parsifa1

This comment was marked as resolved.

@Parsifa1 Parsifa1 marked this pull request as draft October 3, 2025 19:43
@Parsifa1

This comment was marked as resolved.

@Parsifa1 Parsifa1 marked this pull request as ready for review October 3, 2025 22:04
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/commands.rs (1)

416-460: LGTM: Well-structured helper method.

The build_sudo_parts method cleanly separates the elevation command construction logic. The implementation correctly handles elevation program selection, sudo -A flag, and environment variable passing.

Minor note: Line 433 binds _askpass but only checks for its existence. Consider using std::env::var("NH_SUDO_ASKPASS").is_ok() directly if the value isn't needed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4012ba and a7b63c1.

📒 Files selected for processing (1)
  • src/commands.rs (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/commands.rs (1)
src/checks.rs (1)
  • new (338-347)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Test NH on Darwin
  • GitHub Check: Test NH on Linux
  • GitHub Check: Build NH on Darwin
  • GitHub Check: Build NH on Linux
🔇 Additional comments (4)
src/commands.rs (4)

25-27: LGTM: Formatting improvement.

The multi-line formatting improves readability without changing behavior.


33-35: LGTM: Consistent formatting.

The formatting matches the pattern used in get_cached_password above.


468-500: LGTM: Cleaner elevation command construction.

The refactoring eliminates shell command parsing by directly composing command parts using build_sudo_parts. This addresses the escaping issues mentioned in the PR comments (e.g., empty HOME from escaped quotes) and provides a more robust elevation mechanism.


894-904: Test coverage may need adjustment.

The tests correctly verify the current implementation (HOME="" unconditionally on macOS). However, if the HOME setting logic is adjusted to only apply to elevated commands on macOS (as suggested in the earlier comment), these tests should be updated to cover both:

  • Non-elevated commands: HOME should have actual value on all platforms.
  • Elevated commands: HOME="" on macOS, no HOME on other platforms.

Also applies to: 939-947, 1000-1010

@Parsifa1
Copy link
Contributor Author

Parsifa1 commented Oct 9, 2025

@NotAShelf can we give this pr a try?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/commands.rs (1)

1000-1010: Test expectations don't match the new HOME logic.

Same issue as in the previous tests: the test expects HOME="" on macOS for a non-elevated command, but the new logic only sets HOME="" for elevated commands on macOS.

Apply this diff to fix the test expectations:

-    if cfg!(target_os = "macos") {
-      // macOS sets HOME to "" in Nix environment
-      assert!(
-        matches!(cmd.env_vars.get("HOME"), Some(EnvAction::Set(val)) if val.is_empty())
-      );
-    } else {
-      // Other OSes should have the actual HOME value
-      assert!(
-        matches!(cmd.env_vars.get("HOME"), Some(EnvAction::Set(val)) if val == "/test/home")
-      );
-    }
+    // Non-elevated commands should have HOME from environment on all platforms
+    assert!(
+      matches!(cmd.env_vars.get("HOME"), Some(EnvAction::Set(val)) if val == "/test/home")
+    );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8654cb and 3644e2d.

📒 Files selected for processing (1)
  • src/commands.rs (6 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/commands.rs (1)
src/checks.rs (1)
  • new (338-347)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build NH on Darwin
  • GitHub Check: Build NH on Linux
  • GitHub Check: Test NH on Darwin
  • GitHub Check: Test NH on Linux
  • GitHub Check: treewide-checks
🔇 Additional comments (2)
src/commands.rs (2)

299-305: LGTM! Addresses the past review comment correctly.

The HOME="" setting is now correctly scoped to elevated commands on macOS only. This aligns with the PR objectives to fix the "$HOME is not owned by you" warning and addresses the concern raised in the past review comment.


416-460: Solid refactor to eliminate escaping issues.

The new build_sudo_parts helper returns Vec<String> instead of constructing an Exec object, which avoids the shell escaping issues mentioned in the PR comments that caused malformed environment variables (empty HOME). The logic correctly mirrors build_sudo_cmd while producing unescaped string parts suitable for std::process::Command::new().args().

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/commands.rs (1)

492-497: SUDO_ASKPASS inconsistency still present (duplicate issue from past review).

The SUDO_ASKPASS environment variable is only set when the strategy is exactly Force("sudo"), but build_sudo_parts() (line 432) adds the -A flag whenever the resolved program is sudo, regardless of strategy (Auto, Prefer, or Force).

This inconsistency means:

  • ElevationStrategy::Auto or Prefer that resolves to sudo with NH_SUDO_ASKPASS set → -A flag added but SUDO_ASKPASS env NOT set
  • This will cause sudo to fail with "sudo: no askpass program specified"

Apply this diff to check the resolved program name instead of the strategy variant:

-    if let Some(ElevationStrategy::Force("sudo")) = cmd_builder.elevate.as_ref()
-    {
+    // Set SUDO_ASKPASS environment variable when using sudo
+    let sudo_parts = cmd_builder.build_sudo_parts()?;
+    // Check if first part is sudo by examining the resolved program
+    if sudo_parts[0].contains("sudo") {
       if let Ok(askpass) = std::env::var("NH_SUDO_ASKPASS") {
         std_cmd.env("SUDO_ASKPASS", askpass);
       }
     }
+    
+    // Use the sudo_parts we already built
+    let mut std_cmd = std::process::Command::new(&sudo_parts[0]);
+    if sudo_parts.len() > 1 {
+      std_cmd.args(&sudo_parts[1..]);
+    }
-    
-    let mut sudo_parts = cmd_builder.build_sudo_parts()?;
-
-    // Add the target executable and arguments
-    sudo_parts.push(current_exe.to_string_lossy().to_string());
-    let args: Vec<String> = std::env::args().skip(1).collect();
-    sudo_parts.extend(args);
-
-    let mut std_cmd = std::process::Command::new(&sudo_parts[0]);
-    if sudo_parts.len() > 1 {
-      std_cmd.args(&sudo_parts[1..]);
-    }

Note: You'll need to add the executable and args to sudo_parts before the SUDO_ASKPASS check, or restructure to avoid building sudo_parts twice.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3644e2d and 6f934ba.

📒 Files selected for processing (1)
  • src/commands.rs (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/commands.rs (1)
src/checks.rs (1)
  • new (338-347)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build NH on Darwin
  • GitHub Check: Build NH on Linux
  • GitHub Check: Test NH on Linux
  • GitHub Check: Test NH on Darwin
  • GitHub Check: treewide-checks
🔇 Additional comments (1)
src/commands.rs (1)

416-460: LGTM! Clean helper design for building elevation command parts.

The build_sudo_parts() helper cleanly separates the elevation command construction into reusable parts. Returning Vec<String> provides flexibility for assembling commands with std::process::Command in self_elevate_cmd.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/commands.rs (2)

416-460: LGTM! Consider consolidating with build_sudo_cmd if possible.

The build_sudo_parts helper correctly constructs elevation command parts as a Vec<String>, which avoids the shell escaping issues mentioned in the PR discussion. The logic for resolving the program, adding the -A flag, and building environment parts is sound.

Minor observation: There's some code duplication between build_sudo_parts and the existing build_sudo_cmd method (lines 365-414). If build_sudo_cmd is being phased out in favor of the new approach, consider adding a comment or deprecation notice. Otherwise, consider whether the common logic could be extracted to reduce duplication.


480-497: Consider more robust SUDO_ASKPASS handling.

The implementation works correctly but has a fragile check at line 493. The condition sudo_parts[1] == "-A" assumes the -A flag is always at index 1 when present. While this matches the current build_sudo_parts implementation, it could break if that method is refactored to add other flags or arguments before -A.

Apply this diff for a more robust approach:

-    // check if using SUDO_ASKPASS
-    if sudo_parts[1] == "-A" {
+    // Set SUDO_ASKPASS if using sudo with -A flag
+    if sudo_parts.contains(&"-A".to_string()) {
       if let Ok(askpass) = std::env::var("NH_SUDO_ASKPASS") {
         std_cmd.env("SUDO_ASKPASS", askpass);
       }
     }

Alternatively, you could check the resolved program name and NH_SUDO_ASKPASS directly:

// Set SUDO_ASKPASS when using sudo with askpass
let elevation_program = cmd_builder
  .elevate
  .as_ref()
  .unwrap()
  .resolve()?;
  
if elevation_program.file_name().and_then(|n| n.to_str()) == Some("sudo") {
  if let Ok(askpass) = std::env::var("NH_SUDO_ASKPASS") {
    std_cmd.env("SUDO_ASKPASS", askpass);
  }
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f934ba and 395d3c9.

📒 Files selected for processing (1)
  • src/commands.rs (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/commands.rs (1)
src/checks.rs (1)
  • new (338-347)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Build NH on Darwin
  • GitHub Check: Test NH on Linux
  • GitHub Check: Build NH on Linux
  • GitHub Check: Test NH on Darwin
  • GitHub Check: treewide-checks
🔇 Additional comments (1)
src/commands.rs (1)

299-305: LGTM! Verify the fix resolves the warning on macOS.

The conditional self.elevate.is_some() && cfg!(target_os = "macos") correctly applies HOME="" only to elevated commands on macOS, which should resolve the "$HOME is not owned by you" warning per the linked Nix source and PR objectives.

Please verify that running nh clean all on macOS no longer produces the warning. If possible, test both elevated and non-elevated commands to ensure HOME handling is correct in both cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

nh clean all "$HOME is not owned by you"

1 participant