hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 73c1f66606a123d995d5bcab177b5b37f8d85186
parent e1260c73c34647d4841a27b59811a0f7150157bd
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun,  9 Jan 2022 16:29:15 +0100

fs: tweak fs::resolve

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mfs/fs.ha | 11+++++++----
Mhare/module/scan.ha | 8+++++---
Mos/+linux/dirfdfs.ha | 39+++++----------------------------------
3 files changed, 17 insertions(+), 41 deletions(-)

diff --git a/fs/fs.ha b/fs/fs.ha @@ -252,16 +252,19 @@ export fn chown(fs: *fs, path: str, uid: uint, gid: uint) (void | error) = { }; }; -// Resolves a path to its absolute, normalized value. This consoldates ./ and -// ../ sequences, roots the path, and returns a new path. The caller must free -// the return value. +// Resolves a path to its absolute, normalized value. Relative paths will be +// rooted (if supported by the fs implementation), and "." and ".." components +// will be reduced. This function does not follow symlinks: see [[realpath]] if +// you need this behavior. export fn resolve(fs: *fs, path: str) str = { match (fs.resolve) { case null => void; case let f: *resolvefunc => return f(fs, path); }; - abort(); // TODO + static let buf = path::buffer { ... }; + path::set(&buf, path)!; + return path::string(&buf); }; // Returns the next directory entry from an interator, or void if none remain. diff --git a/hare/module/scan.ha b/hare/module/scan.ha @@ -41,9 +41,10 @@ export fn scan(ctx: *context, path: str) (version | error) = { case let ft: filetype => yield ft; }; + let path = fs::resolve(ctx.fs, path); let st = fs::stat(ctx.fs, path)?; let in = input { - path = fs::resolve(ctx.fs, path), + path = strings::dup(path), stat = st, ft = ft, hash = scan_file(ctx, path, &deps)?, @@ -57,7 +58,7 @@ export fn scan(ctx: *context, path: str) (version | error) = { return version { hash = sumbuf, - basedir = path::dirname(fs::resolve(ctx.fs, path)), + basedir = strings::dup(path::dirname(path)), depends = deps, inputs = inputs, ... @@ -303,9 +304,10 @@ fn scan_directory( let iter = fs::iter(ctx.fs, path)?; scan_directory(ctx, ver, sha, path, iter)?; } else { + let path = fs::resolve(ctx.fs, path); let st = fs::stat(ctx.fs, path)?; let in = input { - path = fs::resolve(ctx.fs, path), + path = strings::dup(path), stat = st, ft = type_for_ext(path) as filetype, hash = scan_file(ctx, path, &ver.depends)?, diff --git a/os/+linux/dirfdfs.ha b/os/+linux/dirfdfs.ha @@ -362,42 +362,13 @@ fn fs_chown(fs: *fs::fs, path: str, uid: uint, gid: uint) (void | fs::error) = { }; }; -fn resolve_part(parts: *[]str, part: str) void = { - if (part == ".") { - // no-op - void; - } else if (part == "..") { - if (len(parts) != 0) { - delete(parts[len(parts) - 1]); - }; - } else { - append(parts, part); - }; -}; - fn fs_resolve(fs: *fs::fs, path: str) str = { - let parts: []str = []; - if (!path::abs(path)) { - let iter = path::iter(getcwd()); - for (true) { - match (path::next(&iter)) { - case void => - break; - case let p: str => - resolve_part(&parts, p); - }; - }; - }; - let iter = path::iter(path); - for (true) { - match (path::next(&iter)) { - case void => - break; - case let p: str => - resolve_part(&parts, p); - }; + if (path::abs(path)) { + return path; }; - return path::join(parts...); + static let buf = path::buffer { ... }; + path::set(&buf, os::getcwd(), path)!; + return path::string(&buf); }; fn fs_close(fs: *fs::fs) void = {