mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-07-09 15:17:49 +02:00
fix mulitple bugs
This commit is contained in:
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+52
-2
@@ -2079,7 +2079,7 @@ code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Progress bars on dashboard */
|
/* Progress bars on dashboard */
|
||||||
.progress {
|
.progress:not(.quota-progress) {
|
||||||
min-width: 120px !important;
|
min-width: 120px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3830,6 +3830,8 @@ textarea::selection {
|
|||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
.paper-page .quota-progress .progress-bar {
|
.paper-page .quota-progress .progress-bar {
|
||||||
background: var(--color);
|
background: var(--color);
|
||||||
@@ -4010,6 +4012,21 @@ textarea::selection {
|
|||||||
background: var(--hover-bg-color);
|
background: var(--hover-bg-color);
|
||||||
}
|
}
|
||||||
.paper-table .paper-table-row.repo-inactive { opacity: 0.55; }
|
.paper-table .paper-table-row.repo-inactive { opacity: 0.55; }
|
||||||
|
.paper-table .paper-table-row.repo-error {
|
||||||
|
background: rgba(180, 35, 24, 0.04);
|
||||||
|
border-left: 2px solid #B42318;
|
||||||
|
padding-left: 6px;
|
||||||
|
}
|
||||||
|
.paper-table .paper-table-row.repo-error:hover { background: rgba(180, 35, 24, 0.08); }
|
||||||
|
.dark-mode .paper-table .paper-table-row.repo-error { background: rgba(240, 138, 130, 0.05); border-left-color: #F08A82; }
|
||||||
|
.dark-mode .paper-table .paper-table-row.repo-error:hover { background: rgba(240, 138, 130, 0.1); }
|
||||||
|
.paper-table .cell-status .status-sub-error,
|
||||||
|
.cell-status .status-sub.status-sub-error {
|
||||||
|
color: #B42318;
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
}
|
||||||
|
.dark-mode .paper-table .cell-status .status-sub-error,
|
||||||
|
.dark-mode .cell-status .status-sub.status-sub-error { color: #F08A82; }
|
||||||
.paper-table .cell-anon {
|
.paper-table .cell-anon {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -4450,10 +4467,43 @@ textarea::selection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.paper-page .quota-row { grid-template-columns: 1fr; gap: 14px; padding: 16px; }
|
.paper-page .paper-page-title { font-size: clamp(1.4rem, 6vw, 1.9rem); margin: 4px 0 2px; }
|
||||||
|
.paper-page .paper-page-lede { font-size: 13px; line-height: 1.4; margin-bottom: 0; }
|
||||||
|
.paper-page .btn-ink { padding: 6px 12px; font-size: 13px; }
|
||||||
|
|
||||||
|
.paper-page .quota-row {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 10px 12px;
|
||||||
|
padding: 0;
|
||||||
|
margin: 12px 0 0;
|
||||||
|
}
|
||||||
|
.paper-page .dashboard-filter-row {
|
||||||
|
padding: 8px 0;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.paper-page .quota-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
.paper-page .quota-label { font-size: 10px; letter-spacing: 0.1em; }
|
||||||
|
.paper-page .quota-value { font-size: 11px; }
|
||||||
|
|
||||||
.paper-page .dashboard-filter-row { gap: 8px; }
|
.paper-page .dashboard-filter-row { gap: 8px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.paper-page .paper-page-lede {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.paper-page .quota-row { gap: 8px; }
|
||||||
|
.paper-page .quota-label { font-size: 9px; letter-spacing: 0.06em; }
|
||||||
|
.paper-page .quota-value { font-size: 10px; white-space: nowrap; }
|
||||||
|
}
|
||||||
|
|
||||||
/* Empty state */
|
/* Empty state */
|
||||||
.empty-state {
|
.empty-state {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"repository_not_accessible": "This repository is currently not accessible.",
|
"repository_not_accessible": "This repository is currently not accessible.",
|
||||||
"repo_is_updating": "Anonymous GitHub is still processing the repository, it can take several minutes.",
|
"repo_is_updating": "Anonymous GitHub is still processing the repository, it can take several minutes.",
|
||||||
"invalid_repo": "The provided repository is not valid.",
|
"invalid_repo": "The provided repository is not valid.",
|
||||||
|
"invalid_source_repository": "The repository source name is invalid; expected the form 'owner/name'.",
|
||||||
"repoId_not_defined": "A repository ID must be provided.",
|
"repoId_not_defined": "A repository ID must be provided.",
|
||||||
"repoUrl_not_defined": "The repository URL needs to be defined.",
|
"repoUrl_not_defined": "The repository URL needs to be defined.",
|
||||||
"repoId_already_used": "The repository ID is already used.",
|
"repoId_already_used": "The repository ID is already used.",
|
||||||
@@ -25,6 +26,8 @@
|
|||||||
"branch_not_specified": "The branch is not specified.",
|
"branch_not_specified": "The branch is not specified.",
|
||||||
"branch_not_found": "The branch of the repository cannot be found.",
|
"branch_not_found": "The branch of the repository cannot be found.",
|
||||||
"commit_not_specified": "A commit must be specified.",
|
"commit_not_specified": "A commit must be specified.",
|
||||||
|
"commit_not_found": "The configured commit no longer exists in the source repository. It may have been force-pushed, rebased, or removed.",
|
||||||
|
"repo_renamed": "The source repository appears to have been renamed or moved on GitHub. Please refresh and try again — the cached name has been updated.",
|
||||||
"invalid_commit_format": "The commit hash format is invalid. It must be a hexadecimal string.",
|
"invalid_commit_format": "The commit hash format is invalid. It must be a hexadecimal string.",
|
||||||
"pull_request_not_found": "The requested pull request could not be found.",
|
"pull_request_not_found": "The requested pull request could not be found.",
|
||||||
"pull_request_expired": "This pull request has expired and is no longer available.",
|
"pull_request_expired": "This pull request has expired and is no longer available.",
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
<div
|
<div
|
||||||
class="paper-table-row"
|
class="paper-table-row"
|
||||||
role="row"
|
role="row"
|
||||||
ng-class="{'repo-inactive': repo.status == 'expired' || repo.status == 'removed', 'row-selected': selected[repo.repoId]}"
|
ng-class="{'repo-inactive': repo.status == 'expired' || repo.status == 'removed', 'repo-error': repo.status == 'error', 'row-selected': selected[repo.repoId]}"
|
||||||
ng-repeat="repo in repositories | filter:repoFiler | orderBy:orderBy as filteredRepositories"
|
ng-repeat="repo in repositories | filter:repoFiler | orderBy:orderBy as filteredRepositories"
|
||||||
>
|
>
|
||||||
<div role="cell" style="width: 28px;">
|
<div role="cell" style="width: 28px;">
|
||||||
|
|||||||
@@ -177,7 +177,7 @@
|
|||||||
<div
|
<div
|
||||||
class="paper-table-row"
|
class="paper-table-row"
|
||||||
role="row"
|
role="row"
|
||||||
ng-class="{'repo-inactive': repo.status == 'expired' || repo.status == 'removed'}"
|
ng-class="{'repo-inactive': repo.status == 'expired' || repo.status == 'removed', 'repo-error': repo.status == 'error'}"
|
||||||
ng-repeat="repo in repositories | filter:repoFiler | orderBy:orderBy as filteredRepositories"
|
ng-repeat="repo in repositories | filter:repoFiler | orderBy:orderBy as filteredRepositories"
|
||||||
>
|
>
|
||||||
<div class="cell-anon" role="cell">
|
<div class="cell-anon" role="cell">
|
||||||
@@ -190,8 +190,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell-status" role="cell">
|
<div class="cell-status" role="cell">
|
||||||
<span class="status-dot" ng-class="{'status-removed': repo.status == 'removed' || repo.status == 'expired', 'status-ready': repo.status == 'ready', 'status-error': repo.status == 'error'}"></span>
|
<span class="status-line">
|
||||||
<span ng-bind="repo.status | title"></span>
|
<span class="status-dot" ng-class="{'status-removed': repo.status == 'removed' || repo.status == 'expired', 'status-ready': repo.status == 'ready', 'status-error': repo.status == 'error'}"></span>
|
||||||
|
<span ng-bind="repo.status | title"></span>
|
||||||
|
</span>
|
||||||
|
<span class="status-sub status-sub-error" ng-if="repo.status == 'error' && repo.statusMessage" title="{{repo.statusMessage}}" ng-bind="repo.statusMessage"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell-views num" role="cell" ng-bind="::repo.pageView | number"></div>
|
<div class="cell-views num" role="cell" ng-bind="::repo.pageView | number"></div>
|
||||||
<div class="cell-expires" role="cell" ng-bind="repo.anonymizeDate | humanTime"></div>
|
<div class="cell-expires" role="cell" ng-bind="repo.anonymizeDate | humanTime"></div>
|
||||||
|
|||||||
@@ -179,7 +179,7 @@
|
|||||||
<div
|
<div
|
||||||
class="paper-table-row"
|
class="paper-table-row"
|
||||||
role="row"
|
role="row"
|
||||||
ng-class="{'repo-inactive': item.status == 'expired' || item.status == 'removed' || item.status == 'error'}"
|
ng-class="{'repo-inactive': item.status == 'expired' || item.status == 'removed', 'repo-error': item.status == 'error'}"
|
||||||
ng-repeat="item in items | filter:itemFilter | orderBy:orderBy as filteredItems"
|
ng-repeat="item in items | filter:itemFilter | orderBy:orderBy as filteredItems"
|
||||||
>
|
>
|
||||||
<div class="cell-anon" role="cell">
|
<div class="cell-anon" role="cell">
|
||||||
@@ -206,7 +206,8 @@
|
|||||||
></span>
|
></span>
|
||||||
<span ng-bind="item.status | title"></span>
|
<span ng-bind="item.status | title"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="status-sub" ng-if="item.anonymizeDate" title="Last anonymized {{item.anonymizeDate | humanTime}}" ng-bind="item.anonymizeDate | humanTime"></div>
|
<div class="status-sub status-sub-error" ng-if="item.status == 'error' && item.statusMessage" title="{{item.statusMessage}}" ng-bind="item.statusMessage"></div>
|
||||||
|
<div class="status-sub" ng-if="item.status != 'error' && item.anonymizeDate" title="Last anonymized {{item.anonymizeDate | humanTime}}" ng-bind="item.anonymizeDate | humanTime"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell-views num" role="cell" ng-bind="item.pageView | number"></div>
|
<div class="cell-views num" role="cell" ng-bind="item.pageView | number"></div>
|
||||||
<div class="cell-expires" role="cell">
|
<div class="cell-expires" role="cell">
|
||||||
|
|||||||
+20
-1
@@ -1374,7 +1374,18 @@ angular
|
|||||||
if (res.data.options.expirationDate) {
|
if (res.data.options.expirationDate) {
|
||||||
$scope.options.expirationDate = new Date(res.data.options.expirationDate);
|
$scope.options.expirationDate = new Date(res.data.options.expirationDate);
|
||||||
}
|
}
|
||||||
$scope.details = (await $http.get(`/api/pr/${res.data.source.repositoryFullName}/${res.data.source.pullRequestId}`)).data;
|
try {
|
||||||
|
$scope.details = (await $http.get(`/api/pr/${res.data.source.repositoryFullName}/${res.data.source.pullRequestId}`)).data;
|
||||||
|
} catch (error) {
|
||||||
|
const code = error && error.data && error.data.error;
|
||||||
|
if (code) {
|
||||||
|
$translate("ERRORS." + code).then((translation) => {
|
||||||
|
$scope.addToast({ title: "Error", date: new Date(), body: translation });
|
||||||
|
$scope.error = translation;
|
||||||
|
}, console.error);
|
||||||
|
displayErrorMessage(code);
|
||||||
|
}
|
||||||
|
}
|
||||||
$scope.$apply();
|
$scope.$apply();
|
||||||
},
|
},
|
||||||
() => { $location.url("/404"); }
|
() => { $location.url("/404"); }
|
||||||
@@ -2867,3 +2878,11 @@ angular
|
|||||||
getConference();
|
getConference();
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$(document).on("click", "#navbarSupportedContent .nav-link", function (e) {
|
||||||
|
if ($(this).attr("data-toggle") === "dropdown") return;
|
||||||
|
var $collapse = $("#navbarSupportedContent");
|
||||||
|
if ($collapse.hasClass("show")) {
|
||||||
|
$collapse.collapse("hide");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+49
-8
@@ -6,7 +6,7 @@ import ConferenceModel from "./model/conference/conferences.model";
|
|||||||
import AnonymousError from "./AnonymousError";
|
import AnonymousError from "./AnonymousError";
|
||||||
import { IAnonymizedPullRequestDocument } from "./model/anonymizedPullRequests/anonymizedPullRequests.types";
|
import { IAnonymizedPullRequestDocument } from "./model/anonymizedPullRequests/anonymizedPullRequests.types";
|
||||||
import config from "../config";
|
import config from "../config";
|
||||||
import got from "got";
|
import got, { HTTPError } from "got";
|
||||||
import { octokit } from "./GitHubUtils";
|
import { octokit } from "./GitHubUtils";
|
||||||
import { ContentAnonimizer } from "./anonymize-utils";
|
import { ContentAnonimizer } from "./anonymize-utils";
|
||||||
|
|
||||||
@@ -57,20 +57,61 @@ export default class PullRequest {
|
|||||||
const [owner, repo] = this._model.source.repositoryFullName.split("/");
|
const [owner, repo] = this._model.source.repositoryFullName.split("/");
|
||||||
const pull_number = this._model.source.pullRequestId;
|
const pull_number = this._model.source.pullRequestId;
|
||||||
|
|
||||||
const [prInfo, comments, diff] = await Promise.all([
|
let prInfo;
|
||||||
oct.rest.pulls.get({
|
try {
|
||||||
|
prInfo = await oct.rest.pulls.get({
|
||||||
owner,
|
owner,
|
||||||
repo,
|
repo,
|
||||||
pull_number,
|
pull_number,
|
||||||
}),
|
});
|
||||||
oct.paginate("GET /repos/{owner}/{repo}/issues/{issue_number}/comments", {
|
} catch (err) {
|
||||||
|
if ((err as { status?: number }).status === 404) {
|
||||||
|
throw new AnonymousError("pull_request_not_found", {
|
||||||
|
httpStatus: 404,
|
||||||
|
object: this,
|
||||||
|
cause: err as Error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
const commentsPromise = oct
|
||||||
|
.paginate("GET /repos/{owner}/{repo}/issues/{issue_number}/comments", {
|
||||||
owner: owner,
|
owner: owner,
|
||||||
repo: repo,
|
repo: repo,
|
||||||
issue_number: pull_number,
|
issue_number: pull_number,
|
||||||
per_page: 100,
|
per_page: 100,
|
||||||
}),
|
})
|
||||||
got(`https://github.com/${owner}/${repo}/pull/${pull_number}.diff`),
|
.catch((err): Array<{
|
||||||
]);
|
body?: string | null;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
user?: { login?: string } | null;
|
||||||
|
}> => {
|
||||||
|
if ((err as { status?: number }).status === 404) {
|
||||||
|
console.warn(
|
||||||
|
"[WARN] Failed to fetch PR comments (404), continuing without them",
|
||||||
|
`${owner}/${repo}#${pull_number}`
|
||||||
|
);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
|
||||||
|
const diffPromise = got(
|
||||||
|
`https://github.com/${owner}/${repo}/pull/${pull_number}.diff`
|
||||||
|
).catch((err) => {
|
||||||
|
if (err instanceof HTTPError && err.response.statusCode === 404) {
|
||||||
|
console.warn(
|
||||||
|
"[WARN] Failed to fetch PR diff (404), continuing without it",
|
||||||
|
`${owner}/${repo}#${pull_number}`
|
||||||
|
);
|
||||||
|
return { body: "" };
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
|
||||||
|
const [comments, diff] = await Promise.all([commentsPromise, diffPromise]);
|
||||||
|
|
||||||
this._model.pullRequest = {
|
this._model.pullRequest = {
|
||||||
diff: diff.body,
|
diff: diff.body,
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import { Readable } from "stream";
|
|||||||
import AnonymizedFile from "../AnonymizedFile";
|
import AnonymizedFile from "../AnonymizedFile";
|
||||||
import { SourceBase } from "./Source";
|
import { SourceBase } from "./Source";
|
||||||
import { IFile } from "../model/files/files.types";
|
import { IFile } from "../model/files/files.types";
|
||||||
|
import { octokit } from "../GitHubUtils";
|
||||||
|
import { isConnected } from "../../server/database";
|
||||||
|
import RepositoryModel from "../model/repositories/repositories.model";
|
||||||
|
import AnonymizedRepositoryModel from "../model/anonymizedRepositories/anonymizedRepositories.model";
|
||||||
|
|
||||||
export interface GitHubBaseData {
|
export interface GitHubBaseData {
|
||||||
getToken: () => string | Promise<string>;
|
getToken: () => string | Promise<string>;
|
||||||
@@ -25,3 +29,64 @@ export default abstract class GitHubBase implements SourceBase {
|
|||||||
|
|
||||||
abstract getFiles(progress?: (status: string) => void): Promise<IFile[]>;
|
abstract getFiles(progress?: (status: string) => void): Promise<IFile[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On a 404 from a commit/tree/zip lookup, probe `repos.get` to determine
|
||||||
|
* whether the repository itself is gone, was renamed, or only the commit is
|
||||||
|
* missing. When a rename is detected (via the cached numeric GitHub repo id
|
||||||
|
* on `RepositoryModel.externalId`), the model's `name` is updated in place so
|
||||||
|
* subsequent lookups succeed.
|
||||||
|
*/
|
||||||
|
export async function classifyGitHubMissError(
|
||||||
|
err: unknown,
|
||||||
|
data: GitHubBaseData
|
||||||
|
): Promise<"repo_not_found" | "commit_not_found" | "repo_renamed"> {
|
||||||
|
const status = (err as { status?: number }).status;
|
||||||
|
if (status !== 404) return "repo_not_found";
|
||||||
|
const oct = octokit(await data.getToken());
|
||||||
|
try {
|
||||||
|
await oct.repos.get({
|
||||||
|
owner: data.organization,
|
||||||
|
repo: data.repoName,
|
||||||
|
});
|
||||||
|
return "commit_not_found";
|
||||||
|
} catch {
|
||||||
|
// Repo no longer exists at owner/repo. Try to recover via the cached
|
||||||
|
// numeric GitHub id — if the repo was renamed, GET /repositories/{id}
|
||||||
|
// resolves to its new full_name. See #409.
|
||||||
|
if (!isConnected) return "repo_not_found";
|
||||||
|
const dbModel = await RepositoryModel.findOne({
|
||||||
|
name: data.organization + "/" + data.repoName,
|
||||||
|
});
|
||||||
|
const ghId =
|
||||||
|
typeof dbModel?.externalId === "string" &&
|
||||||
|
dbModel.externalId.startsWith("gh_")
|
||||||
|
? dbModel.externalId.slice(3)
|
||||||
|
: null;
|
||||||
|
if (!dbModel || !ghId) return "repo_not_found";
|
||||||
|
try {
|
||||||
|
const r = await oct.request("GET /repositories/{id}", { id: ghId });
|
||||||
|
const newName = (r?.data as { full_name?: string } | undefined)
|
||||||
|
?.full_name;
|
||||||
|
if (newName && newName !== dbModel.name) {
|
||||||
|
const oldName = dbModel.name;
|
||||||
|
dbModel.name = newName;
|
||||||
|
await dbModel.save();
|
||||||
|
// Propagate the rename to every anonymized repo that referenced
|
||||||
|
// the old source name, so subsequent lookups (admin diagnostic,
|
||||||
|
// streaming, download, update cron) all hit the correct GitHub
|
||||||
|
// location without the user having to recreate the configuration.
|
||||||
|
await AnonymizedRepositoryModel.updateMany(
|
||||||
|
{ "source.repositoryName": oldName },
|
||||||
|
{ $set: { "source.repositoryName": newName } }
|
||||||
|
);
|
||||||
|
data.organization = newName.split("/")[0];
|
||||||
|
data.repoName = newName.split("/")[1];
|
||||||
|
return "repo_renamed";
|
||||||
|
}
|
||||||
|
return "repo_not_found";
|
||||||
|
} catch {
|
||||||
|
return "repo_not_found";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { Readable } from "stream";
|
|||||||
import { OctokitResponse } from "@octokit/types";
|
import { OctokitResponse } from "@octokit/types";
|
||||||
|
|
||||||
import storage from "../storage";
|
import storage from "../storage";
|
||||||
import GitHubBase, { GitHubBaseData } from "./GitHubBase";
|
import GitHubBase, {
|
||||||
|
GitHubBaseData,
|
||||||
|
classifyGitHubMissError,
|
||||||
|
} from "./GitHubBase";
|
||||||
import { FILE_TYPE } from "../storage/Storage";
|
import { FILE_TYPE } from "../storage/Storage";
|
||||||
import { octokit } from "../GitHubUtils";
|
import { octokit } from "../GitHubUtils";
|
||||||
import AnonymousError from "../AnonymousError";
|
import AnonymousError from "../AnonymousError";
|
||||||
@@ -30,7 +33,8 @@ export default class GitHubDownload extends GitHubBase {
|
|||||||
try {
|
try {
|
||||||
response = await this.getZipUrl();
|
response = await this.getZipUrl();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new AnonymousError("repo_not_found", {
|
const code = await classifyGitHubMissError(error, this.data);
|
||||||
|
throw new AnonymousError(code, {
|
||||||
httpStatus: (error as { status?: number }).status || 404,
|
httpStatus: (error as { status?: number }).status || 404,
|
||||||
object: this.data,
|
object: this.data,
|
||||||
cause: error as Error,
|
cause: error as Error,
|
||||||
|
|||||||
@@ -55,12 +55,35 @@ export class GitHubRepository {
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const oct = octokit(opt.accessToken);
|
const oct = octokit(opt.accessToken);
|
||||||
const commit = await oct.repos.getCommit({
|
try {
|
||||||
owner: this.owner,
|
const commit = await oct.repos.getCommit({
|
||||||
repo: this.repo,
|
owner: this.owner,
|
||||||
ref: sha,
|
repo: this.repo,
|
||||||
});
|
ref: sha,
|
||||||
return commit.data;
|
});
|
||||||
|
return commit.data;
|
||||||
|
} catch (error) {
|
||||||
|
const status = (error as { status?: number }).status;
|
||||||
|
if (status === 404) {
|
||||||
|
// Distinguish: does the repo itself still exist?
|
||||||
|
let repoExists = false;
|
||||||
|
try {
|
||||||
|
await oct.repos.get({ owner: this.owner, repo: this.repo });
|
||||||
|
repoExists = true;
|
||||||
|
} catch {
|
||||||
|
repoExists = false;
|
||||||
|
}
|
||||||
|
throw new AnonymousError(
|
||||||
|
repoExists ? "commit_not_found" : "repo_not_found",
|
||||||
|
{
|
||||||
|
httpStatus: 404,
|
||||||
|
cause: error as Error,
|
||||||
|
object: this,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async branches(opt: {
|
async branches(opt: {
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import AnonymizedFile from "../AnonymizedFile";
|
import AnonymizedFile from "../AnonymizedFile";
|
||||||
import GitHubBase, { GitHubBaseData } from "./GitHubBase";
|
import GitHubBase, {
|
||||||
|
GitHubBaseData,
|
||||||
|
classifyGitHubMissError,
|
||||||
|
} from "./GitHubBase";
|
||||||
import storage from "../storage";
|
import storage from "../storage";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import got from "got";
|
import got from "got";
|
||||||
@@ -274,7 +277,8 @@ export default class GitHubStream extends GitHubBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (status === 404) {
|
if (status === 404) {
|
||||||
throw new AnonymousError("repo_not_found", {
|
const code = await classifyGitHubMissError(error, this.data);
|
||||||
|
throw new AnonymousError(code, {
|
||||||
httpStatus: 404,
|
httpStatus: 404,
|
||||||
object: this.data,
|
object: this.data,
|
||||||
cause: error as Error,
|
cause: error as Error,
|
||||||
|
|||||||
Reference in New Issue
Block a user