diff --git a/fetching/git-fetcher/src/index.ts b/fetching/git-fetcher/src/index.ts index 74d24dfd5e0..f1d0943c35b 100644 --- a/fetching/git-fetcher/src/index.ts +++ b/fetching/git-fetcher/src/index.ts @@ -49,7 +49,9 @@ export function createGitFetcher (createOpts: CreateGitFetcherOptions) { // the linking of files to the store is in progress. return addFilesFromDir({ cafsDir: cafs.cafsDir, - dir: tempLocation, + dir: resolution.path + ? path.join(tempLocation, resolution.path) + : tempLocation, filesIndexFile: opts.filesIndexFile, readManifest: opts.readManifest, pkg: opts.pkg, diff --git a/resolving/git-resolver/src/index.ts b/resolving/git-resolver/src/index.ts index 0e3fcc565ec..f4693a09c43 100644 --- a/resolving/git-resolver/src/index.ts +++ b/resolving/git-resolver/src/index.ts @@ -37,6 +37,7 @@ export function createGitResolver ( resolution = { commit, repo: parsedSpec.fetchSpec, + path: parsedSpec.path, type: 'git', } as ({ type: string } & object) } diff --git a/resolving/git-resolver/src/parsePref.ts b/resolving/git-resolver/src/parsePref.ts index c6d96b7b8d4..50d9e7f1651 100644 --- a/resolving/git-resolver/src/parsePref.ts +++ b/resolving/git-resolver/src/parsePref.ts @@ -1,5 +1,5 @@ // cspell:ignore sshurl -import urlLib, { URL } from 'url' +import urlLib, { URL, type URLSearchParams } from 'url' import { fetch } from '@pnpm/fetch' import git from 'graceful-git' @@ -17,6 +17,7 @@ export interface HostedPackageSpec { normalizedPref: string gitCommittish: string | null gitRange?: string + path?: string } const gitProtocols = new Set([ @@ -48,6 +49,7 @@ export async function parsePref (pref: string): Promise { // esli }, normalizedPref: `git+${httpsUrl}`, ...setGitCommittish(hosted.committish), + ...setSubFolder(httpsUrl), } } else { try { @@ -122,6 +126,7 @@ async function fromHostedGit (hosted: any): Promise { // esli }, normalizedPref: hosted.shortcut(), ...setGitCommittish(hosted.committish), + ...setSubFolder(fetchSpec!), } } @@ -153,6 +158,22 @@ function setGitCommittish (committish: string | null) { return { gitCommittish: committish } } +function setSubFolder (url: string) { + let query: URLSearchParams + try { + query = new urlLib.URL(url).searchParams + } catch (err) { + // maybe it's not a valid url, just ignore it + return {} + } + + const path = query.get('path') ?? null + if (Array.isArray(path)) { + throw new Error(`Only one sub folder is supported, but got ${path.length}: ${path.join(', ')}`) + } + return path ? { path } : {} +} + // handle SCP-like URLs // see https://github.com/yarnpkg/yarn/blob/5682d55/src/util/git.js#L103 function correctUrl (gitUrl: string) { diff --git a/resolving/resolver-base/src/index.ts b/resolving/resolver-base/src/index.ts index a49cff36fe9..feb1728b7e4 100644 --- a/resolving/resolver-base/src/index.ts +++ b/resolving/resolver-base/src/index.ts @@ -20,6 +20,7 @@ export interface DirectoryResolution { export interface GitResolution { commit: string repo: string + path?: string type: 'git' }