fix: relative path resolution

comma operator...
This commit is contained in:
2026-01-18 16:35:20 +08:00
parent dcb853ea0a
commit 9aee36a0e2
5 changed files with 23 additions and 10 deletions

View File

@@ -11,6 +11,7 @@ import { coerceToPath, coerceToString, StringCoercionMode } from "./conversion";
import { getPathValue } from "../path"; import { getPathValue } from "../path";
import type { NixStringContext, StringWithContext } from "../string-context"; import type { NixStringContext, StringWithContext } from "../string-context";
import { mkStringWithContext } from "../string-context"; import { mkStringWithContext } from "../string-context";
import { isPath } from "./type-check";
export const importFunc = (path: NixValue): NixValue => { export const importFunc = (path: NixValue): NixValue => {
const context: NixStringContext = new Set(); const context: NixStringContext = new Set();
@@ -143,8 +144,9 @@ export const fetchTarball = (args: NixValue): string => {
export const fetchGit = (args: NixValue): NixAttrs => { export const fetchGit = (args: NixValue): NixAttrs => {
const forced = force(args); const forced = force(args);
if (typeof forced === "string") { if (typeof forced === "string" || isPath(forced)) {
const result: FetchGitResult = Deno.core.ops.op_fetch_git(forced, null, null, false, false, false, null); const path = coerceToPath(forced);
const result: FetchGitResult = Deno.core.ops.op_fetch_git(path, null, null, false, false, false, null);
return { return {
outPath: result.out_path, outPath: result.out_path,
rev: result.rev, rev: result.rev,

View File

@@ -5,6 +5,7 @@
import { import {
HAS_CONTEXT, HAS_CONTEXT,
isNixPath, isNixPath,
NixPath,
type NixAttrs, type NixAttrs,
type NixBool, type NixBool,
type NixFloat, type NixFloat,
@@ -40,7 +41,7 @@ export const isList = (e: NixValue): e is NixList => Array.isArray(force(e));
export const isNull = (e: NixValue): e is NixNull => force(e) === null; export const isNull = (e: NixValue): e is NixNull => force(e) === null;
export const isPath = (e: NixValue): boolean => { export const isPath = (e: NixValue): e is NixPath => {
const val = force(e); const val = force(e);
return isNixPath(val); return isNixPath(val);
}; };

View File

@@ -7,12 +7,12 @@ use crate::ir::*;
pub(crate) fn compile(expr: &Ir, ctx: &impl CodegenContext) -> String { pub(crate) fn compile(expr: &Ir, ctx: &impl CodegenContext) -> String {
let code = expr.compile(ctx); let code = expr.compile(ctx);
let debug_prefix = if std::env::var("NIX_JS_DEBUG_THUNKS").is_ok() { let debug_prefix = if std::env::var("NIX_JS_DEBUG_THUNKS").is_ok() {
"Nix.DEBUG_THUNKS.enabled=true," "Nix.DEBUG_THUNKS.enabled=true;"
} else { } else {
"" ""
}; };
let cur_dir = ctx.get_current_dir().display().to_string().escape_quote(); let cur_dir = ctx.get_current_dir().display().to_string().escape_quote();
format!("({}currentDir={},{})", debug_prefix, cur_dir, code) format!("(()=>{{{}const currentDir={};return {}}})()", debug_prefix, cur_dir, code)
} }
trait Compile<Ctx: CodegenContext> { trait Compile<Ctx: CodegenContext> {

View File

@@ -70,7 +70,6 @@ impl Context {
Ok(Self { ctx, runtime, store }) Ok(Self { ctx, runtime, store })
} }
#[tracing::instrument(skip(self), fields(expr_len = expr.len()))]
pub fn eval_code(&mut self, expr: &str) -> Result<Value> { pub fn eval_code(&mut self, expr: &str) -> Result<Value> {
tracing::info!("Starting evaluation"); tracing::info!("Starting evaluation");
self.ctx.current_file = Some( self.ctx.current_file = Some(
@@ -196,7 +195,6 @@ impl Ctx {
.expect("current_file doesn't have a parent dir") .expect("current_file doesn't have a parent dir")
} }
#[tracing::instrument(skip(self), fields(expr_len = expr.len()))]
fn compile_code(&mut self, expr: &str) -> Result<String> { fn compile_code(&mut self, expr: &str) -> Result<String> {
tracing::debug!("Parsing Nix expression"); tracing::debug!("Parsing Nix expression");
let root = rnix::Root::parse(expr); let root = rnix::Root::parse(expr);

View File

@@ -121,13 +121,24 @@ fn op_resolve_path(
#[string] current_dir: String, #[string] current_dir: String,
#[string] path: String, #[string] path: String,
) -> std::result::Result<String, NixError> { ) -> std::result::Result<String, NixError> {
let _span = tracing::debug_span!("op_resolve_path").entered();
tracing::debug!(current_dir, path);
// If already absolute, return as-is // If already absolute, return as-is
if path.starts_with('/') { if path.starts_with('/') {
return Ok(path); return Ok(path);
} }
// Resolve relative path against current file directory (or CWD) // Resolve relative path against current file directory (or CWD)
let current_dir = PathBuf::from(current_dir).join(&path); let current_dir = if !path.starts_with("~/") {
let mut dir = PathBuf::from(current_dir);
dir.push(path);
dir
} else {
let mut dir = std::env::home_dir()
.ok_or("home dir not defined")?;
dir.push(&path[2..]);
dir
};
let mut normalized = PathBuf::new(); let mut normalized = PathBuf::new();
for component in current_dir.components() { for component in current_dir.components() {
match component { match component {
@@ -140,6 +151,7 @@ fn op_resolve_path(
Component::Normal(c) => normalized.push(c), Component::Normal(c) => normalized.push(c),
} }
} }
tracing::debug!(normalized = normalized.display().to_string());
Ok(normalized.to_string_lossy().to_string()) Ok(normalized.to_string_lossy().to_string())
} }
@@ -305,7 +317,7 @@ fn op_store_path(
state: &mut OpState, state: &mut OpState,
#[string] path: String, #[string] path: String,
) -> std::result::Result<String, NixError> { ) -> std::result::Result<String, NixError> {
use crate::store::{validate_store_path, StoreBackend}; use crate::store::{StoreBackend, validate_store_path};
use std::sync::Arc; use std::sync::Arc;
let store = state.borrow::<Arc<StoreBackend>>(); let store = state.borrow::<Arc<StoreBackend>>();