backend-common: fix azure readTree subpath handling

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-09-10 12:08:08 +02:00
parent 0408b0d7ff
commit 8cfeb5fe08
2 changed files with 19 additions and 13 deletions
@@ -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();