backend-common: fix azure readTree subpath handling
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -81,14 +81,14 @@ describe('AzureUrlReader', () => {
|
||||
url: 'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml&version=GBmaster',
|
||||
config: createConfig(),
|
||||
response: expect.objectContaining({
|
||||
url: 'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml&version=master',
|
||||
url: 'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?api-version=6.0&path=my-template.yaml&version=master',
|
||||
}),
|
||||
},
|
||||
{
|
||||
url: 'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml',
|
||||
config: createConfig(),
|
||||
response: expect.objectContaining({
|
||||
url: 'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml',
|
||||
url: 'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?api-version=6.0&path=my-template.yaml',
|
||||
}),
|
||||
},
|
||||
{
|
||||
@@ -125,14 +125,12 @@ describe('AzureUrlReader', () => {
|
||||
{
|
||||
url: 'https://api.com/a/b/blob/master/path/to/c.yaml',
|
||||
config: createConfig(),
|
||||
error:
|
||||
'Incorrect URL: https://api.com/a/b/blob/master/path/to/c.yaml, Error: Wrong Azure Devops URL or Invalid file path',
|
||||
error: 'Azure URL must point to a git repository',
|
||||
},
|
||||
{
|
||||
url: 'com/a/b/blob/master/path/to/c.yaml',
|
||||
config: createConfig(),
|
||||
error:
|
||||
'Incorrect URL: com/a/b/blob/master/path/to/c.yaml, TypeError: Invalid URL: com/a/b/blob/master/path/to/c.yaml',
|
||||
error: 'Invalid URL: com/a/b/blob/master/path/to/c.yaml',
|
||||
},
|
||||
{
|
||||
url: '',
|
||||
|
||||
@@ -23,11 +23,9 @@ import {
|
||||
ScmIntegrations,
|
||||
} from '@backstage/integration';
|
||||
import fetch from 'cross-fetch';
|
||||
import parseGitUrl from 'git-url-parse';
|
||||
import { Minimatch } from 'minimatch';
|
||||
import { Readable } from 'stream';
|
||||
import { NotFoundError, NotModifiedError } from '@backstage/errors';
|
||||
import { stripFirstDirectoryFromPath } from './tree/util';
|
||||
import {
|
||||
ReadTreeResponseFactory,
|
||||
ReaderFactory,
|
||||
@@ -129,28 +127,38 @@ export class AzureUrlReader implements UrlReader {
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
// When downloading a zip archive from azure on a subpath we get an extra directory
|
||||
// layer added at the top. With for example the file /a/b/c.txt and a download of
|
||||
// /a/b, we'll see /b/c.txt in the zip archive. This picks out /b so that we can remove it.
|
||||
let subpath;
|
||||
const path = new URL(url).searchParams.get('path');
|
||||
if (path) {
|
||||
subpath = path.split('/').filter(Boolean).slice(-1)[0];
|
||||
}
|
||||
|
||||
return await this.deps.treeResponseFactory.fromZipArchive({
|
||||
stream: archiveAzureResponse.body as unknown as Readable,
|
||||
etag: commitSha,
|
||||
filter: options?.filter,
|
||||
subpath,
|
||||
});
|
||||
}
|
||||
|
||||
async search(url: string, options?: SearchOptions): Promise<SearchResponse> {
|
||||
const { filepath } = parseGitUrl(url);
|
||||
const matcher = new Minimatch(filepath);
|
||||
const treeUrl = new URL(url);
|
||||
|
||||
const path = treeUrl.searchParams.get('path');
|
||||
const matcher = path && new Minimatch(path.replace(/^\/+/, ''));
|
||||
|
||||
// TODO(freben): For now, read the entire repo and filter through that. In
|
||||
// a future improvement, we could be smart and try to deduce that non-glob
|
||||
// prefixes (like for filepaths such as some-prefix/**/a.yaml) can be used
|
||||
// to get just that part of the repo.
|
||||
const treeUrl = new URL(url);
|
||||
treeUrl.searchParams.delete('path');
|
||||
treeUrl.pathname = treeUrl.pathname.replace(/\/+$/, '');
|
||||
|
||||
const tree = await this.readTree(treeUrl.toString(), {
|
||||
etag: options?.etag,
|
||||
filter: path => matcher.match(stripFirstDirectoryFromPath(path)),
|
||||
filter: p => (matcher ? matcher.match(p) : true),
|
||||
});
|
||||
const files = await tree.files();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user