import {Component} from 'react'; import {RouteComponentProps} from 'react-router'; import * as Sentry from '@sentry/react'; import {addErrorMessage} from 'sentry/actionCreators/indicator'; import {Client} from 'sentry/api'; import Button from 'sentry/components/button'; import {Body, Main} from 'sentry/components/layouts/thirds'; import LoadingIndicator from 'sentry/components/loadingIndicator'; import {Panel} from 'sentry/components/panels'; import {IconCommit} from 'sentry/icons'; import {t} from 'sentry/locale'; import {Organization, Repository} from 'sentry/types'; import getDisplayName from 'sentry/utils/getDisplayName'; import withApi from 'sentry/utils/withApi'; import withOrganization from 'sentry/utils/withOrganization'; import withRepositories from 'sentry/utils/withRepositories'; import EmptyMessage from 'sentry/views/settings/components/emptyMessage'; import {ReleaseContext} from '..'; // These props are required when using this HoC type DependentProps = RouteComponentProps<{orgId: string; release: string}, {}>; type HoCsProps = { api: Client; organization: Organization; repositories?: Repository[]; repositoriesError?: Error; repositoriesLoading?: boolean; }; type State = { isLoading: boolean; releaseRepos: Repository[]; activeReleaseRepo?: Repository; }; function withReleaseRepos
( WrappedComponent: React.ComponentType
) { class WithReleaseRepos extends Component
{
static displayName = `withReleaseRepos(${getDisplayName(WrappedComponent)})`;
state: State = {
releaseRepos: [],
isLoading: true,
};
componentDidMount() {
this.fetchReleaseRepos();
}
componentDidUpdate(prevProps: P & HoCsProps, prevState: State) {
if (
this.props.params.release !== prevProps.params.release ||
(!!prevProps.repositoriesLoading && !this.props.repositoriesLoading)
) {
this.fetchReleaseRepos();
return;
}
if (
prevState.releaseRepos.length !== this.state.releaseRepos.length ||
prevProps.location.query?.activeRepo !== this.props.location.query?.activeRepo
) {
this.setActiveReleaseRepo(this.props);
}
}
static contextType = ReleaseContext;
setActiveReleaseRepo(props: P & HoCsProps) {
const {releaseRepos, activeReleaseRepo} = this.state;
if (!releaseRepos.length) {
return;
}
const activeCommitRepo = props.location.query?.activeRepo;
if (!activeCommitRepo) {
this.setState({
activeReleaseRepo: releaseRepos[0] ?? null,
});
return;
}
if (activeCommitRepo === activeReleaseRepo?.name) {
return;
}
const matchedRepository = releaseRepos.find(
commitRepo => commitRepo.name === activeCommitRepo
);
if (matchedRepository) {
this.setState({
activeReleaseRepo: matchedRepository,
});
return;
}
addErrorMessage(t('The repository you were looking for was not found.'));
}
async fetchReleaseRepos() {
const {params, api, repositories, repositoriesLoading} = this.props;
if (repositoriesLoading === undefined || repositoriesLoading === true) {
return;
}
if (!repositories?.length) {
this.setState({isLoading: false});
return;
}
const {release, orgId} = params;
const {project} = this.context;
this.setState({isLoading: true});
try {
const releasePath = encodeURIComponent(release);
const releaseRepos = await api.requestPromise(
`/projects/${orgId}/${project.slug}/releases/${releasePath}/repositories/`
);
this.setState({releaseRepos, isLoading: false});
this.setActiveReleaseRepo(this.props);
} catch (error) {
Sentry.captureException(error);
addErrorMessage(
t(
'An error occurred while trying to fetch the repositories of the release: %s',
release
)
);
}
}
render() {
const {isLoading, activeReleaseRepo, releaseRepos} = this.state;
const {repositoriesLoading, repositories, params, router, location, organization} =
this.props;
if (isLoading || repositoriesLoading) {
return