integration: implement AzureUrl

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-09-10 11:40:16 +02:00
parent 5a41c16fc7
commit 63e3745fe3
+145 -11
View File
@@ -14,14 +14,77 @@
* limitations under the License.
*/
const VERSION_PREFIX_GIT_BRANCH = 'GB';
export class AzureUrl {
/**
* Parses an azure URL as copied from the browser address bar.
*
* Throws an error if the URL is not a valid azure repo URL.
*/
static fromRepoUrl(_repoUrl: string): AzureUrl {
throw new Error('not implemented');
static fromRepoUrl(repoUrl: string): AzureUrl {
const url = new URL(repoUrl);
let owner;
let project;
let repo;
const parts = url.pathname.split('/').map(part => decodeURIComponent(part));
if (parts[2] === '_git') {
owner = parts[1];
project = repo = parts[3];
} else if (parts[3] === '_git') {
owner = parts[1];
project = parts[2];
repo = parts[4];
}
if (!owner || !project || !repo) {
throw new Error('Azure URL must point to a git repository');
}
const path = url.searchParams.get('path') ?? undefined;
let ref;
const version = url.searchParams.get('version');
if (version) {
const prefix = version.slice(0, 2);
if (prefix !== 'GB') {
throw new Error('Azure URL version must point to a git branch');
}
ref = version.slice(2);
}
return new AzureUrl(url.origin, owner, project, repo, path, ref);
}
#origin: string;
#owner: string;
#project: string;
#repo: string;
#path?: string;
#ref?: string;
private constructor(
origin: string,
owner: string,
project: string,
repo: string,
path?: string,
ref?: string,
) {
this.#origin = origin;
this.#owner = owner;
this.#project = project;
this.#repo = repo;
this.#path = path;
this.#ref = ref;
}
#baseUrl(...parts: string[]): URL {
const url = new URL(this.#origin);
url.pathname = parts.map(part => encodeURIComponent(part)).join('/');
return url;
}
/**
@@ -30,7 +93,21 @@ export class AzureUrl {
* Throws an error if the URL is not a valid azure repo URL.
*/
toRepoUrl(): string {
throw new Error('not implemented');
let url;
if (this.#project === this.#repo) {
url = this.#baseUrl(this.#owner, '_git', this.#repo);
} else {
url = this.#baseUrl(this.#owner, this.#project, '_git', this.#repo);
}
if (this.#path) {
url.searchParams.set('path', this.#path);
}
if (this.#ref) {
url.searchParams.set('version', VERSION_PREFIX_GIT_BRANCH + this.#ref);
}
return url.toString();
}
/**
@@ -39,7 +116,29 @@ export class AzureUrl {
* Throws an error if the URL does not point to a file.
*/
toFileUrl(): string {
throw new Error('not implemented');
if (!this.#path) {
throw new Error(
'Azure URL must point to a specific path to be able to download a file',
);
}
const url = this.#baseUrl(
this.#owner,
this.#project,
'_apis',
'git',
'repositories',
this.#repo,
'items',
);
url.searchParams.set('api-version', '6.0');
url.searchParams.set('path', this.#path);
if (this.#ref) {
url.searchParams.set('version', this.#ref);
}
return url.toString();
}
/**
@@ -48,7 +147,27 @@ export class AzureUrl {
* Throws an error if the URL does not point to a repo.
*/
toArchiveUrl(): string {
throw new Error('not implemented');
const url = this.#baseUrl(
this.#owner,
this.#project,
'_apis',
'git',
'repositories',
this.#repo,
'items',
);
url.searchParams.set('recursionLevel', 'full');
url.searchParams.set('download', 'true');
url.searchParams.set('api-version', '6.0');
if (this.#path) {
url.searchParams.set('scopePath', this.#path);
}
if (this.#ref) {
url.searchParams.set('version', this.#ref);
}
return url.toString();
}
/**
@@ -57,41 +176,56 @@ export class AzureUrl {
* Throws an error if the URL does not point to a commit.
*/
toCommitsUrl(): string {
throw new Error('not implemented');
const url = this.#baseUrl(
this.#owner,
this.#project,
'_apis',
'git',
'repositories',
this.#repo,
'commits',
);
url.searchParams.set('api-version', '6.0');
if (this.#ref) {
url.searchParams.set('searchCriteria.itemVersion.version', this.#ref);
}
return url.toString();
}
/**
* Returns the name of the owner, a user or an organization.
*/
getOwner(): string {
throw new Error('not implemented');
return this.#owner;
}
/**
* Returns the name of the project.
*/
getProject(): string {
throw new Error('not implemented');
return this.#project;
}
/**
* Returns the name of the repo.
*/
getRepo(): string {
throw new Error('not implemented');
return this.#repo;
}
/**
* Returns the file path within the repo if the URL contains one.
*/
getPath(): string | undefined {
throw new Error('not implemented');
return this.#path;
}
/**
* Returns the git ref in the repo if the URL contains one.
*/
getRef(): string | undefined {
throw new Error('not implemented');
return this.#ref;
}
}