From 87f85c7db71bc6d23ca060c79e08e39b280f4721 Mon Sep 17 00:00:00 2001 From: Axel Ricard Date: Thu, 5 Oct 2023 16:44:53 +0200 Subject: [PATCH] add some utils functions for path manipulation --- src/dscanner/utils.d | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/dscanner/utils.d b/src/dscanner/utils.d index 4c4c9f2..accc237 100644 --- a/src/dscanner/utils.d +++ b/src/dscanner/utils.d @@ -6,6 +6,7 @@ import std.conv : to; import std.encoding : BOM, BOMSeq, EncodingException, getBOM; import std.format : format; import std.file : exists, read; +import std.path: isValidPath; private void processBOM(ref ubyte[] sourceCode, string fname) { @@ -128,6 +129,55 @@ string[] expandArgs(string[] args) return rVal; } +package string absoluteNormalizedPath(in string path) +{ + import std.path: absolutePath, buildNormalizedPath; + + return path.absolutePath().buildNormalizedPath(); +} + +private bool areSamePath(in string path1, in string path2) +in(path1.isValidPath && path2.isValidPath) +{ + return path1.absoluteNormalizedPath() == path2.absoluteNormalizedPath(); +} + +unittest +{ + assert(areSamePath("/abc/efg", "/abc/efg")); + assert(areSamePath("/abc/../abc/efg", "/abc/efg")); + assert(!areSamePath("/abc/../abc/../efg", "/abc/efg")); +} + +package bool isSubpathOf(in string potentialSubPath, in string base) +in(base.isValidPath && potentialSubPath.isValidPath) +{ + import std.path: isValidPath, relativePath; + import std.algorithm: canFind; + + if(areSamePath(base, potentialSubPath)) + return true; + + const relative = relativePath( + potentialSubPath.absoluteNormalizedPath(), + base.absoluteNormalizedPath() + ); + + // No '..' in the relative paths means that potentialSubPath + // is actually a descendant of base + return !relative.canFind(".."); +} + +unittest +{ + const base = "/abc/efg"; + assert("/abc/efg/".isSubpathOf(base)); + assert("/abc/efg/hij/".isSubpathOf(base)); + assert("/abc/efg/hij/../kel".isSubpathOf(base)); + assert(!"/abc/kel".isSubpathOf(base)); + assert(!"/abc/efg/../kel".isSubpathOf(base)); +} + /** * Allows to build access chains of class members as done with the $(D ?.) operator * in other languages. In the chain, any $(D null) member that is a class instance