From 9c2a7c6b823162714a303df9407c86951975d144 Mon Sep 17 00:00:00 2001 From: Dylan Conway Date: Fri, 13 Jan 2023 16:04:06 -0800 Subject: git cache folder resolver --- src/install/install.zig | 27 +++++++++++++++++++----- src/install/repository.zig | 13 ++++++++++++ src/install/resolution.zig | 34 +++++++++---------------------- src/install/resolvers/folder_resolver.zig | 30 +++++++++++++++++++++++---- 4 files changed, 71 insertions(+), 33 deletions(-) diff --git a/src/install/install.zig b/src/install/install.zig index 3221605cd..66d9d508b 100644 --- a/src/install/install.zig +++ b/src/install/install.zig @@ -555,7 +555,7 @@ const Task = struct { const repo_name = lockfile.str(git_repo.repo); var url_buf: [bun.MAX_PATH_BYTES]u8 = undefined; - const url = if (this.request.git_clone.version.tag == .github) git_repo.getGitHubURL(lockfile, &url_buf) else git_repo.getURL(lockfile, &url_buf); + const url = if (this.request.git_clone.version.tag == .github) git_repo.getGitHubURL(lockfile, &url_buf) else git_repo.getURLForClone(lockfile, &url_buf); var temp_dir_path_buf: [bun.MAX_PATH_BYTES]u8 = undefined; const temp_dir = std.os.getFdPath(this.package_manager.getTemporaryDirectory().dir.fd, &temp_dir_path_buf) catch unreachable; @@ -580,7 +580,7 @@ const Task = struct { process.stdin_behavior = .Close; const term = process.spawnAndWait() catch { - this.log.addErrorFmt(null, logger.Loc.Empty, allocator, "Failed to spawn git process to clone github dependency \"{s}\"", .{repo_name}) catch unreachable; + this.log.addErrorFmt(null, logger.Loc.Empty, allocator, "Failed to spawn git process to clone git dependency \"{s}\"", .{repo_name}) catch unreachable; this.status = .fail; this.package_manager.resolve_tasks.writeItem(this.*) catch unreachable; return; @@ -598,7 +598,7 @@ const Task = struct { const package_json_file = std.fs.openFileAbsolute(package_json_path, .{}) catch { this.status = .fail; - this.log.addErrorFmt(null, logger.Loc.Empty, allocator, "Failed to find package.json for github dependency \"{s}\"", .{repo_name}) catch unreachable; + this.log.addErrorFmt(null, logger.Loc.Empty, allocator, "Failed to find package.json for git dependency \"{s}\"", .{repo_name}) catch unreachable; this.package_manager.resolve_tasks.writeItem(this.*) catch unreachable; return; }; @@ -612,7 +612,7 @@ const Task = struct { if (package_json_file_size < "{\"name\":\"\",\"version\":\"\"}".len + repo_name.len + "0.0.0".len) { // package.json smaller than minimum possible this.status = .fail; - this.log.addErrorFmt(null, logger.Loc.Empty, allocator, "Invalid package.json for github dependency \"{s}\"", .{repo_name}) catch unreachable; + this.log.addErrorFmt(null, logger.Loc.Empty, allocator, "Invalid package.json for git dependency \"{s}\"", .{repo_name}) catch unreachable; this.package_manager.resolve_tasks.writeItem(this.*) catch unreachable; return; } @@ -3626,8 +3626,9 @@ pub const PackageManager = struct { const git_cache_dir = manager.getGitCacheDirectory().dir; git_cache_dir.deleteTree(package_name) catch unreachable; + const version = task.request.git_clone.version; var destination_name_buf: [bun.MAX_PATH_BYTES]u8 = undefined; - const destination_name = try git_repo.getCacheDirectoryForGitHub(manager, &destination_name_buf); + const destination_name = if (version.tag == .github) try git_repo.getCacheDirectoryForGitHub(manager, &destination_name_buf) else try git_repo.getCacheDirectory(manager, &destination_name_buf); std.fs.rename(temp_dir, package_name, git_cache_dir, destination_name) catch unreachable; temp_dir.deleteTree(package_name) catch unreachable; @@ -5973,6 +5974,22 @@ pub const PackageManager = struct { installer.cache_dir = .{ .dir = std.fs.cwd() }; } }, + .git => { + const repo: Repository = resolution.value.git; + const temp = repo.getCacheDirectory(this.manager, &cached_package_folder_name_buf) catch unreachable; + cached_package_folder_name_buf[temp.len] = 0; + const cache_dir_subpath: stringZ = std.meta.assumeSentinel(cached_package_folder_name_buf[0..temp.len], 0); + installer.cache_dir_subpath = cache_dir_subpath; + installer.cache_dir = .{ .dir = this.manager.getGitCacheDirectory().dir }; + }, + .github => { + const repo: Repository = resolution.value.github; + const temp = repo.getCacheDirectoryForGitHub(this.manager, &cached_package_folder_name_buf) catch unreachable; + cached_package_folder_name_buf[temp.len] = 0; + const cache_dir_subpath: stringZ = std.meta.assumeSentinel(cached_package_folder_name_buf[0..temp.len], 0); + installer.cache_dir_subpath = cache_dir_subpath; + installer.cache_dir = .{ .dir = this.manager.getGitCacheDirectory().dir }; + }, .symlink => { const directory = this.manager.globalLinkDir() catch |err| { if (comptime log_level != .silent) { diff --git a/src/install/repository.zig b/src/install/repository.zig index d53fca8d5..f6c663bec 100644 --- a/src/install/repository.zig +++ b/src/install/repository.zig @@ -99,6 +99,19 @@ pub const Repository = extern struct { return buf[0..i]; } + pub fn getURLForClone(this: Repository, lockfile: *Lockfile, buf: *[bun.MAX_PATH_BYTES]u8) []u8 { + var url = this.getURL(lockfile, buf); + + // replace ':' with '/' if it exists to make a valid url + if (strings.lastIndexOfChar(url, ':')) |j| { + if (url[j + 1] != '/') { + url[j] = '/'; + } + } + + return url; + } + pub fn getCacheDirectoryForGitHub(this: Repository, manager: *PackageManager, buf: *[bun.MAX_PATH_BYTES]u8) ![]u8 { var url_buf: [bun.MAX_PATH_BYTES]u8 = undefined; const url = this.getGitHubURL(manager.lockfile, &url_buf); diff --git a/src/install/resolution.zig b/src/install/resolution.zig index d21855d7c..eb531b811 100644 --- a/src/install/resolution.zig +++ b/src/install/resolution.zig @@ -26,8 +26,7 @@ pub const Resolution = extern struct { return switch (lhs.tag) { .npm => lhs.value.npm.order(rhs.value.npm, lhs_buf, rhs_buf), .local_tarball => lhs.value.local_tarball.order(&rhs.value.local_tarball, lhs_buf, rhs_buf), - .git_ssh => lhs.value.git_ssh.order(&rhs.value.git_ssh, lhs_buf, rhs_buf), - .git_http => lhs.value.git_http.order(&rhs.value.git_http, lhs_buf, rhs_buf), + .git => lhs.value.git.order(&rhs.value.git, lhs_buf, rhs_buf), .folder => lhs.value.folder.order(&rhs.value.folder, lhs_buf, rhs_buf), .remote_tarball => lhs.value.remote_tarball.order(&rhs.value.remote_tarball, lhs_buf, rhs_buf), .workspace => lhs.value.workspace.order(&rhs.value.workspace, lhs_buf, rhs_buf), @@ -43,8 +42,7 @@ pub const Resolution = extern struct { switch (this.tag) { .npm => this.value.npm.count(buf, Builder, builder), .local_tarball => builder.count(this.value.local_tarball.slice(buf)), - .git_ssh => builder.count(this.value.git_ssh.slice(buf)), - .git_http => builder.count(this.value.git_http.slice(buf)), + .git => this.value.git.count(buf, Builder, builder), .folder => builder.count(this.value.folder.slice(buf)), .remote_tarball => builder.count(this.value.remote_tarball.slice(buf)), .workspace => builder.count(this.value.workspace.slice(buf)), @@ -66,11 +64,8 @@ pub const Resolution = extern struct { .local_tarball => Resolution.Value{ .local_tarball = builder.append(String, this.value.local_tarball.slice(buf)), }, - .git_ssh => Resolution.Value{ - .git_ssh = builder.append(String, this.value.git_ssh.slice(buf)), - }, - .git_http => Resolution.Value{ - .git_http = builder.append(String, this.value.git_http.slice(buf)), + .git => Resolution.Value{ + .git = this.value.git.clone(buf, Builder, builder), }, .folder => Resolution.Value{ .folder = builder.append(String, this.value.folder.slice(buf)), @@ -123,13 +118,8 @@ pub const Resolution = extern struct { lhs_string_buf, rhs_string_buf, ), - .git_ssh => lhs.value.git_ssh.eql( - rhs.value.git_ssh, - lhs_string_buf, - rhs_string_buf, - ), - .git_http => lhs.value.git_http.eql( - rhs.value.git_http, + .git => lhs.value.git.eql( + rhs.value.git, lhs_string_buf, rhs_string_buf, ), @@ -183,8 +173,7 @@ pub const Resolution = extern struct { switch (formatter.resolution.tag) { .npm => try writer.writeAll(formatter.resolution.value.npm.url.slice(formatter.buf)), .local_tarball => try writer.writeAll(formatter.resolution.value.local_tarball.slice(formatter.buf)), - .git_ssh => try std.fmt.format(writer, "git+ssh://{s}", .{formatter.resolution.value.git_ssh.slice(formatter.buf)}), - .git_http => try std.fmt.format(writer, "https://{s}", .{formatter.resolution.value.git_http.slice(formatter.buf)}), + .git => try formatter.resolution.value.git.formatAs("git", formatter.buf, layout, opts, writer), .folder => try writer.writeAll(formatter.resolution.value.folder.slice(formatter.buf)), .remote_tarball => try writer.writeAll(formatter.resolution.value.remote_tarball.slice(formatter.buf)), .github => try formatter.resolution.value.github.formatAs("github", formatter.buf, layout, opts, writer), @@ -205,8 +194,7 @@ pub const Resolution = extern struct { switch (formatter.resolution.tag) { .npm => try formatter.resolution.value.npm.version.fmt(formatter.buf).format(layout, opts, writer), .local_tarball => try writer.writeAll(formatter.resolution.value.local_tarball.slice(formatter.buf)), - .git_ssh => try std.fmt.format(writer, "git+ssh://{s}", .{formatter.resolution.value.git_ssh.slice(formatter.buf)}), - .git_http => try std.fmt.format(writer, "https://{s}", .{formatter.resolution.value.git_http.slice(formatter.buf)}), + .git => try formatter.resolution.value.git.formatAs("git", formatter.buf, layout, opts, writer), .folder => try writer.writeAll(formatter.resolution.value.folder.slice(formatter.buf)), .remote_tarball => try writer.writeAll(formatter.resolution.value.remote_tarball.slice(formatter.buf)), .github => try formatter.resolution.value.github.formatAs("github", formatter.buf, layout, opts, writer), @@ -228,8 +216,7 @@ pub const Resolution = extern struct { /// File path to a tarball relative to the package root local_tarball: String, - git_ssh: String, - git_http: String, + git: Repository, folder: String, @@ -258,8 +245,7 @@ pub const Resolution = extern struct { github = 16, gitlab = 24, - git_ssh = 32, - git_http = 33, + git = 33, symlink = 64, diff --git a/src/install/resolvers/folder_resolver.zig b/src/install/resolvers/folder_resolver.zig index b9e222f22..cf7b6eb05 100644 --- a/src/install/resolvers/folder_resolver.zig +++ b/src/install/resolvers/folder_resolver.zig @@ -71,6 +71,22 @@ pub const FolderResolution = union(Tag) { pub fn count(_: @This(), comptime Builder: type, _: Builder, _: JSAst.Expr) void {} }; + pub const GitCacheFolderResolver = struct { + repository: Repository, + version_tag: Dependency.Version.Tag, + + pub fn resolve(this: @This(), comptime Builder: type, _: Builder, _: JSAst.Expr) !Resolution { + return Resolution{ + .tag = if (this.version_tag == .git) Resolution.Tag.git else Resolution.Tag.github, + .value = .{ + .git = this.repository, + }, + }; + } + + pub fn count(_: @This(), comptime Builder: type, _: Builder, _: JSAst.Expr) void {} + }; + pub fn normalizePackageJSONPath(global_or_relative: GlobalOrRelative, joined: *[bun.MAX_PATH_BYTES]u8, non_normalized_path: string) [2]string { var abs: string = ""; var rel: string = ""; @@ -257,8 +273,11 @@ pub const FolderResolution = union(Tag) { json_bytes, version, Features.git, - Resolver, - Resolver{ .folder_path = rel }, + GitCacheFolderResolver, + GitCacheFolderResolver{ + .repository = if (version.tag == .git) version.value.git else version.value.github, + .version_tag = version.tag, + }, ), } catch |err| { if (err == error.FileNotFound) { @@ -323,8 +342,11 @@ pub const FolderResolution = union(Tag) { abs, version, Features.git, - Resolver, - Resolver{ .folder_path = rel }, + GitCacheFolderResolver, + GitCacheFolderResolver{ + .repository = if (version.tag == .git) version.value.git else version.value.github, + .version_tag = version.tag, + }, ), } catch |err| { if (err == error.FileNotFound) { -- cgit v1.2.3