aboutsummaryrefslogtreecommitdiff
path: root/src/resolver/resolve_path.zig
diff options
context:
space:
mode:
authorGravatar Dylan Conway <35280289+dylan-conway@users.noreply.github.com> 2023-05-12 07:33:07 -0700
committerGravatar GitHub <noreply@github.com> 2023-05-12 07:33:07 -0700
commit4d5d0d075a597400175d410db8b8dcfcc8016623 (patch)
tree7d71234b4438bd83641d52e33d61b6040b205e62 /src/resolver/resolve_path.zig
parentc815716899d8ace52b9c6ebd494735a7f8de9bf8 (diff)
downloadbun-4d5d0d075a597400175d410db8b8dcfcc8016623.tar.gz
bun-4d5d0d075a597400175d410db8b8dcfcc8016623.tar.zst
bun-4d5d0d075a597400175d410db8b8dcfcc8016623.zip
`root` bundle option (#2859)
* handle multiple output files and `[dir]` * get the realpath of `root_dir` * duplicate output paths * add `rootdir` to `JSBundler` * use realpath of input file * add tests for naming and root --------- Co-authored-by: Dave Caruso <me@paperdave.net>
Diffstat (limited to 'src/resolver/resolve_path.zig')
-rw-r--r--src/resolver/resolve_path.zig143
1 files changed, 143 insertions, 0 deletions
diff --git a/src/resolver/resolve_path.zig b/src/resolver/resolve_path.zig
index da21f3ec1..c5ffdc626 100644
--- a/src/resolver/resolve_path.zig
+++ b/src/resolver/resolve_path.zig
@@ -36,6 +36,145 @@ inline fn @"is ../"(slice: []const u8) bool {
return strings.hasPrefixComptime(slice, "../");
}
+pub fn getIfExistsLongestCommonPathGeneric(input: []const []const u8, comptime separator: u8, comptime isPathSeparator: IsSeparatorFunc) ?[]const u8 {
+ var min_length: usize = std.math.maxInt(usize);
+ for (input) |str| {
+ min_length = @min(str.len, min_length);
+ }
+
+ var index: usize = 0;
+ var last_common_separator: ?usize = null;
+
+ // try to use an unrolled version of this loop
+ switch (input.len) {
+ 0 => {
+ return "";
+ },
+ 1 => {
+ return input[0];
+ },
+ 2 => {
+ while (index < min_length) : (index += 1) {
+ if (input[0][index] != input[1][index]) {
+ if (last_common_separator == null) return null;
+ break;
+ }
+ if (@call(.always_inline, isPathSeparator, .{input[0][index]})) {
+ last_common_separator = index;
+ }
+ }
+ },
+ 3 => {
+ while (index < min_length) : (index += 1) {
+ if (nqlAtIndex(3, index, input)) {
+ if (last_common_separator == null) return null;
+ break;
+ }
+ if (@call(.always_inline, isPathSeparator, .{input[0][index]})) {
+ last_common_separator = index;
+ }
+ }
+ },
+ 4 => {
+ while (index < min_length) : (index += 1) {
+ if (nqlAtIndex(4, index, input)) {
+ if (last_common_separator == null) return null;
+ break;
+ }
+ if (@call(.always_inline, isPathSeparator, .{input[0][index]})) {
+ last_common_separator = index;
+ }
+ }
+ },
+ 5 => {
+ while (index < min_length) : (index += 1) {
+ if (nqlAtIndex(5, index, input)) {
+ if (last_common_separator == null) return null;
+ break;
+ }
+ if (@call(.always_inline, isPathSeparator, .{input[0][index]})) {
+ last_common_separator = index;
+ }
+ }
+ },
+ 6 => {
+ while (index < min_length) : (index += 1) {
+ if (nqlAtIndex(6, index, input)) {
+ if (last_common_separator == null) return null;
+ break;
+ }
+ if (@call(.always_inline, isPathSeparator, .{input[0][index]})) {
+ last_common_separator = index;
+ }
+ }
+ },
+ 7 => {
+ while (index < min_length) : (index += 1) {
+ if (nqlAtIndex(7, index, input)) {
+ if (last_common_separator == null) return null;
+ break;
+ }
+ if (@call(.always_inline, isPathSeparator, .{input[0][index]})) {
+ last_common_separator = index;
+ }
+ }
+ },
+ 8 => {
+ while (index < min_length) : (index += 1) {
+ if (nqlAtIndex(8, index, input)) {
+ if (last_common_separator == null) return null;
+ break;
+ }
+ if (@call(.always_inline, isPathSeparator, .{input[0][index]})) {
+ last_common_separator = index;
+ }
+ }
+ },
+ else => {
+ var string_index: usize = 1;
+ while (string_index < input.len) : (string_index += 1) {
+ while (index < min_length) : (index += 1) {
+ if (input[0][index] != input[string_index][index]) {
+ if (last_common_separator == null) return null;
+ break;
+ }
+ }
+ if (index == min_length) index -= 1;
+ if (@call(.always_inline, isPathSeparator, .{input[0][index]})) {
+ last_common_separator = index;
+ }
+ }
+ },
+ }
+
+ if (index == 0) {
+ return &([_]u8{separator});
+ }
+
+ if (last_common_separator == null) {
+ return &([_]u8{'.'});
+ }
+
+ // The above won't work for a case like this:
+ // /app/public/index.js
+ // /app/public
+ // It will return:
+ // /app/
+ // It should return:
+ // /app/public/
+ // To detect /app/public is actually a folder, we do one more loop through the strings
+ // and say, "do one of you have a path separator after what we thought was the end?"
+ for (input) |str| {
+ if (str.len > index) {
+ if (@call(.always_inline, isPathSeparator, .{str[index]})) {
+ return str[0 .. index + 1];
+ }
+ }
+ }
+
+ return input[0][0 .. last_common_separator.? + 1];
+}
+
// TODO: is it faster to determine longest_common_separator in the while loop
// or as an extra step at the end?
// only boether to check if this function appears in benchmarking
@@ -170,6 +309,10 @@ pub fn longestCommonPath(input: []const []const u8) []const u8 {
return longestCommonPathGeneric(input, '/', isSepAny);
}
+pub fn getIfExistsLongestCommonPath(input: []const []const u8) ?[]const u8 {
+ return getIfExistsLongestCommonPathGeneric(input, '/', isSepAny);
+}
+
pub fn longestCommonPathWindows(input: []const []const u8) []const u8 {
return longestCommonPathGeneric(input, std.fs.path.sep_windows, isSepWin32);
}