import { useQuery, useQueryClient } from '@tanstack/react-query';
import { GitCommitVerticalIcon } from 'lucide-react';
import { ButtonLink } from '#/components/atoms/button-link.jsx';
import { Link } from '#/components/atoms/link.jsx';
import { AuthorFacepile } from '#/components/molecules/author-facepile.jsx';
import { Breadcrumbs } from '#/components/molecules/breadcrumbs.jsx';
import { CommitCheckStatus } from '#/components/molecules/commit-check-status.jsx';
import { EmptyState } from '#/components/molecules/empty-state.jsx';
import { ListBox } from '#/components/molecules/list-box.jsx';
import { ListSkeleton } from '#/components/molecules/list-skeleton.jsx';
import { PageHead } from '#/components/molecules/page-head.jsx';
import { PageNotice } from '#/components/molecules/page-notice.jsx';
import { ReadingRepo } from '#/components/molecules/reading-repo.jsx';
import { RefSelect } from '#/components/molecules/ref-select.jsx';
import { Screen } from '#/components/molecules/screen.jsx';
import { loadAuthors } from '#/lib/authors.js';
import { PULL_COMMIT_LIMIT, pullsHref } from '#/lib/collab.js';
import { timeAgo } from '#/lib/format.js';
import { isEmpty, repoRecord, repoSize } from '#/lib/git.js';
import { useNavigate } from '#/lib/navigation.jsx';
import { logKey, readLog } from '#/lib/source.js';
const LIMIT = PULL_COMMIT_LIMIT;
/**
* The commits on a ref, or the commits one pull request carries.
*
* A pull request's log is not its branch's: a branch reaches back through
* everything it was cut from, and what somebody reading a pull request wants
* is the commits it added. `base..tip` asks for those, from the copy that
* holds them.
*/
export function CommitsPage({ repo, refName, path, range, from, space }) {
const navigate = useNavigate();
const record = repoRecord(repo, space);
// The tip of a range, which the way to its pull request names.
const tip = range ? range.split('..')[1] : null;
const pulls = useQueryClient().getQueryData(['pulls', repo, space ?? '']);
const { data, error } = useQuery({
queryKey: logKey(repo, refName, range, from, space, path),
enabled: Boolean(record) && !isEmpty(record) && !range,
queryFn: () =>
readLog(repo, { refName, range, from, limit: LIMIT, space, path }),
});
// The rows wait for the authors, so a face never lands after its row.
const authors = useQuery({
queryKey: ['authors'],
queryFn: loadAuthors,
staleTime: Number.POSITIVE_INFINITY,
});
const listed = data && (authors.isSuccess || authors.isError);
if (!record) {
return No such repository.;
}
const at = from ? `/${encodeURIComponent(from)}` : '';
const commitHref = (sha) => `/${encodeURIComponent(repo)}/commit${at}/${sha}`;
// An empty repository has no ref for the log to read, so the listing
// says so rather than asking the server for a ref that cannot exist.
if (isEmpty(record) && !range) {
return (
}
title="No commits yet"
description="This repository has no commits. Push the first one and it appears here."
/>
);
}
// The page heads itself the way a forge heads a history: a title, and for
// one path's history the path it is for. A pull request's commits carry
// the way back to the pull request, which no tab above names.
const refChip = (
{refName}
);
const head = range ? (
The whole pull request as one diff
}
meta={Every commit the pull request carries.}
/>
) : (
History foron
{refChip}
) : (
on
{refChip}
)
}
/>
);
return (
{!range && (