gitea-repository-provider
Version:
repository provider for gitea
235 lines (203 loc) • 5.07 kB
JavaScript
import { matcher } from "matching-iterator";
import { streamToString } from "browser-stream-util";
import {
StreamContentEntryMixin,
BufferContentEntry,
ContentEntry,
CollectionEntry
} from "content-entry";
import {
Branch,
CommitResult,
boolean_attribute,
count_attribute,
default_attribute
} from "repository-provider";
import { join } from "./util.mjs";
/**
*
*
*/
export class GiteaBranch extends Branch {
static get attributeMapping() {
return {
full_name: "displayName"
};
}
static get attributes() {
return {
...super.attributes,
user_can_merge: boolean_attribute,
user_can_push: boolean_attribute,
required_approvals: count_attribute,
enable_status_check: boolean_attribute,
effective_branch_protection_name: default_attribute
};
}
async *entries(patterns) {
const { json } = await this.provider.fetchJSON(
join("repos", this.repository.fullName, "git/trees", await this.refId) +
"?recursive=true"
);
for (const entry of matcher(json.tree, patterns, {
name: "path"
})) {
const options = { mode: parseInt(entry.mode, 8)};
yield entry.type === "tree"
? new CollectionEntry(entry.path, options)
: new (this.name === "master"
? GiteaMasterOnlyContentEntry
: GiteaContentEntry)(entry.path, options, this);
}
}
async removeEntries(entries) {
for await (const entry of entries) {
await this.provider.fetch(
join("repos", this.repository.fullName, "contents", entry.name),
{
method: "DELETE",
body: JSON.stringify({ branch: this.name, message: "", sha: "" })
}
);
}
}
async sha(path) {
const { json } = await this.provider.fetchJSON(
join("repos", this.repository.fullName, "contents", path) +
"#" +
this.name
);
console.log("SHA",json);
return json.sha;
}
/**
* Writes content into the branch.
* @param {ContentEntry} entry
* @param {string} message
* @return {Promise<ContentEntry>} written content with sha values set
*/
async writeEntry(entry, message) {
const buffer = await entry.buffer;
const decoder = new TextDecoder("utf8");
const content = btoa(decoder.decode(buffer));
const date = new Date();
const body = JSON.stringify({
message,
branch: this.name,
content,
sha: await this.sha(entry.name),
dates: {
committer: date.toISOString()
}
});
const { json, response } = await this.provider.fetchJSON(
join("repos", this.repository.fullName, "contents", entry.name),
{
method: "PUT",
body
}
);
if (!response.ok) {
console.error(body);
throw new Error(response.statusText);
}
entry.sha = json.sha;
return entry;
}
/**
* Commit entries.
* @param {string} message commit message
* @param {ContentEntry[]} entries content to be commited
* @param {Object} [options]
* @return {Promise<CommitResult>}
*/
async commit(message, entries, options) {
const updates = await Promise.all(
entries.map(entry => this.writeEntry(entry, message))
);
// TODO hack
return {
ref: `refs/heads/${this.name}`
};
}
}
/**
* works for all branches
*
*/
class GiteaContentEntry extends BufferContentEntry {
constructor(name, options, branch) {
super(name, options);
this.branch = branch;
}
get provider() {
return this.branch.provider;
}
get buffer() {
return this.getBuffer();
}
set buffer(value)
{
this._buffer = value;
}
async getBuffer() {
const url = join(
"repos",
this.branch.repository.fullName,
"contents",
this.name + "?ref=" + this.branch.name
);
const result = await this.provider.fetch(url);
const body = await result.json();
return Buffer.from(body.content, "base64");
}
async getString() {
const url = join(
"repos",
this.branch.repository.fullName,
"contents",
this.name + "?ref=" + this.branch.name
);
const result = await this.provider.fetch(url);
const body = await result.json();
return Buffer.from(body.content, "base64").toString();
}
get string() {
return this.getString();
}
}
/**
* only works for master branch
*
*/
class GiteaMasterOnlyContentEntry extends StreamContentEntryMixin(
ContentEntry
) {
constructor(name, options, branch) {
super(name, options);
this.branch = branch;
}
get provider() {
return this.branch.provider;
}
get readStream() {
return this.getReadStream();
}
async getReadStream() {
const url = join(
"repos",
this.branch.repository.fullName,
"raw",
this.name
);
const result = await this.provider.fetch(url);
return await result.body;
}
async getString() {
return streamToString(await this.getReadStream());
}
// @ts-ignore
get string() {
return this.getString();
}
}