mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-27 17:19:42 -04:00
Fix/git sync issues (#5626)
* Display the push/pull/checkout errors correctly * use branch name to refresh the workspace * fix checkout * fetch the staged changes inside the modal * fix password login with git
This commit is contained in:
1 parent
21c78170b2
commit
9a4e5caa86
6 files changed
+108
-37
No files matched your search
@@ -312,7 +312,7 @@ export class GitVCS {
|
||||
|
||||
async fetch(
|
||||
singleBranch: boolean,
|
||||
depth: number,
|
||||
depth?: number,
|
||||
gitCredentials?: GitCredentials | null,
|
||||
) {
|
||||
console.log('[git] Fetch remote=origin');
|
||||
@@ -352,13 +352,20 @@ export class GitVCS {
|
||||
console.log('[git] Checkout', {
|
||||
branch,
|
||||
});
|
||||
const branches = await this.listBranches();
|
||||
const localBranches = await this.listBranches();
|
||||
const remoteBranches = await this.listRemoteBranches();
|
||||
const branches = [...localBranches, ...remoteBranches];
|
||||
|
||||
if (branches.includes(branch)) {
|
||||
await git.checkout({ ...this._baseOpts, ref: branch, remote: 'origin' });
|
||||
await git.checkout({
|
||||
...this._baseOpts,
|
||||
ref: branch,
|
||||
remote: 'origin',
|
||||
});
|
||||
} else {
|
||||
await this.branch(branch, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async undoPendingChanges(fileFilter?: string[]) {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useFetcher, useParams } from 'react-router-dom';
|
||||
import { docsGitSync } from '../../../common/documentation';
|
||||
import { GitRepository } from '../../../models/git-repository';
|
||||
import { getOauth2FormatName } from '../../../sync/git/utils';
|
||||
import { GitRepoLoaderData, PushToGitRemoteResult } from '../../routes/git-actions';
|
||||
import { GitRepoLoaderData, PullFromGitRemoteResult, PushToGitRemoteResult } from '../../routes/git-actions';
|
||||
import { type DropdownHandle, Dropdown } from '../base/dropdown/dropdown';
|
||||
import { DropdownButton } from '../base/dropdown/dropdown-button';
|
||||
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
|
||||
@@ -34,7 +34,7 @@ export const GitSyncDropdown: FC<Props> = ({ className, gitRepository }) => {
|
||||
const [isGitStagingModalOpen, setIsGitStagingModalOpen] = useState(false);
|
||||
|
||||
const gitPushFetcher = useFetcher<PushToGitRemoteResult>();
|
||||
const gitPullFetcher = useFetcher();
|
||||
const gitPullFetcher = useFetcher<PullFromGitRemoteResult>();
|
||||
const gitCheckoutFetcher = useFetcher();
|
||||
const gitRepoDataFetcher = useFetcher<GitRepoLoaderData>();
|
||||
|
||||
@@ -50,8 +50,6 @@ export const GitSyncDropdown: FC<Props> = ({ className, gitRepository }) => {
|
||||
useEffect(() => {
|
||||
const errors = [
|
||||
...gitPushFetcher.data?.errors ?? [],
|
||||
...gitPullFetcher.data?.errors ?? [],
|
||||
...gitCheckoutFetcher.data?.errors ?? [],
|
||||
];
|
||||
if (errors.length > 0) {
|
||||
showAlert({
|
||||
@@ -59,7 +57,31 @@ export const GitSyncDropdown: FC<Props> = ({ className, gitRepository }) => {
|
||||
message: errors.join('\n'),
|
||||
});
|
||||
}
|
||||
}, [gitCheckoutFetcher.data?.errors, gitPullFetcher.data?.errors, gitPushFetcher.data?.errors]);
|
||||
}, [gitPushFetcher.data?.errors]);
|
||||
|
||||
useEffect(() => {
|
||||
const errors = [
|
||||
...gitPullFetcher.data?.errors ?? [],
|
||||
];
|
||||
if (errors.length > 0) {
|
||||
showAlert({
|
||||
title: 'Pull Failed',
|
||||
message: errors.join('\n'),
|
||||
});
|
||||
}
|
||||
}, [gitPullFetcher.data?.errors]);
|
||||
|
||||
useEffect(() => {
|
||||
const errors = [
|
||||
...gitCheckoutFetcher.data?.errors ?? [],
|
||||
];
|
||||
if (errors.length > 0) {
|
||||
showAlert({
|
||||
title: 'Checkout Failed',
|
||||
message: errors.join('\n'),
|
||||
});
|
||||
}
|
||||
}, [gitCheckoutFetcher.data?.errors]);
|
||||
|
||||
async function handlePush({ force }: { force: boolean }) {
|
||||
gitPushFetcher.submit({
|
||||
@@ -82,7 +104,7 @@ export const GitSyncDropdown: FC<Props> = ({ className, gitRepository }) => {
|
||||
const isLoading = gitRepoDataFetcher.state === 'loading';
|
||||
const isButton = !gitRepository || (isLoading && !gitRepoDataFetcher.data) || (gitRepoDataFetcher.data && 'errors' in gitRepoDataFetcher.data);
|
||||
|
||||
const { log, branches, branch: currentBranch, remoteBranches, changes, statusNames } = (gitRepoDataFetcher.data && 'log' in gitRepoDataFetcher.data) ? gitRepoDataFetcher.data : { log: [], branches: [], branch: '', remoteBranches: [], changes: [], statusNames: {} };
|
||||
const { log, branches, branch: currentBranch, remoteBranches } = (gitRepoDataFetcher.data && 'log' in gitRepoDataFetcher.data) ? gitRepoDataFetcher.data : { log: [], branches: [], branch: '', remoteBranches: [] };
|
||||
|
||||
let dropdown: React.ReactNode = null;
|
||||
|
||||
@@ -236,12 +258,11 @@ export const GitSyncDropdown: FC<Props> = ({ className, gitRepository }) => {
|
||||
/>
|
||||
}
|
||||
{isGitLogModalOpen && <GitLogModal branch={currentBranch} logs={log} onHide={() => setIsGitLogModalOpen(false)} />}
|
||||
{isGitStagingModalOpen && <GitStagingModal
|
||||
changes={changes}
|
||||
branch={currentBranch}
|
||||
statusNames={statusNames}
|
||||
onHide={() => setIsGitStagingModalOpen(false)}
|
||||
/>}
|
||||
{isGitStagingModalOpen &&
|
||||
<GitStagingModal
|
||||
onHide={() => setIsGitStagingModalOpen(false)}
|
||||
/>
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
@@ -5,7 +5,7 @@ import { useFetcher, useParams } from 'react-router-dom';
|
||||
|
||||
import { strings } from '../../../common/strings';
|
||||
import * as models from '../../../models';
|
||||
import { CommitToGitRepoResult, GitChange, GitRollbackChangesResult } from '../../routes/git-actions';
|
||||
import { CommitToGitRepoResult, GitChangesLoaderData, GitRollbackChangesResult } from '../../routes/git-actions';
|
||||
import { IndeterminateCheckbox } from '../base/indeterminate-checkbox';
|
||||
import { type ModalHandle, Modal, ModalProps } from '../base/modal';
|
||||
import { ModalBody } from '../base/modal-body';
|
||||
@@ -24,16 +24,7 @@ interface Item {
|
||||
editable: boolean;
|
||||
}
|
||||
|
||||
type Props = ModalProps & {
|
||||
changes: GitChange[];
|
||||
branch: string;
|
||||
statusNames: Record<string, string>;
|
||||
};
|
||||
|
||||
export const GitStagingModal: FC<Props> = ({
|
||||
changes,
|
||||
branch,
|
||||
statusNames,
|
||||
export const GitStagingModal: FC<ModalProps> = ({
|
||||
onHide,
|
||||
}) => {
|
||||
const { organizationId, projectId, workspaceId } = useParams() as {
|
||||
@@ -45,7 +36,7 @@ export const GitStagingModal: FC<Props> = ({
|
||||
const formRef = useRef<HTMLFormElement>(null);
|
||||
const [checkAllModified, setCheckAllModified] = React.useState(false);
|
||||
const [checkAllUnversioned, setCheckAllUnversioned] = React.useState(false);
|
||||
|
||||
const gitChangesFetcher = useFetcher<GitChangesLoaderData>();
|
||||
const gitCommitFetcher = useFetcher<CommitToGitRepoResult>();
|
||||
const rollbackFetcher = useFetcher<GitRollbackChangesResult>();
|
||||
|
||||
@@ -53,6 +44,22 @@ export const GitStagingModal: FC<Props> = ({
|
||||
modalRef.current?.show();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (gitChangesFetcher.state === 'idle' && !gitChangesFetcher.data) {
|
||||
gitChangesFetcher.load(`/organization/${organizationId}/project/${projectId}/workspace/${workspaceId}/git/changes`);
|
||||
}
|
||||
}, [organizationId, projectId, workspaceId, gitChangesFetcher]);
|
||||
|
||||
const {
|
||||
changes,
|
||||
branch,
|
||||
statusNames,
|
||||
} = gitChangesFetcher.data || {
|
||||
changes: [],
|
||||
branch: '',
|
||||
statusNames: {},
|
||||
};
|
||||
|
||||
const hasChanges = Boolean(changes.length);
|
||||
|
||||
const modifiedChanges = changes.filter(i => !i.status.includes('added'));
|
||||
|
||||
@@ -41,6 +41,7 @@ import Root from './routes/root';
|
||||
import { initializeSentry } from './sentry';
|
||||
|
||||
const Project = lazy(() => import('./routes/project'));
|
||||
const Workspace = lazy(() => import('./routes/workspace'));
|
||||
const UnitTest = lazy(() => import('./routes/unit-test'));
|
||||
const Debug = lazy(() => import('./routes/debug'));
|
||||
const Design = lazy(() => import('./routes/design'));
|
||||
@@ -123,6 +124,7 @@ const router = createMemoryRouter(
|
||||
path: ':workspaceId',
|
||||
id: ':workspaceId',
|
||||
loader: async (...args) => (await import('./routes/workspace')).workspaceLoader(...args),
|
||||
element: <Suspense fallback={<AppLoadingIndicator />}><Workspace /></Suspense>,
|
||||
children: [
|
||||
{
|
||||
path: `${ACTIVITY_DEBUG}`,
|
||||
|
||||
@@ -46,8 +46,6 @@ export type GitRepoLoaderData = {
|
||||
branches: string[];
|
||||
remoteBranches: string[];
|
||||
gitRepository: GitRepository | null;
|
||||
changes: GitChange[];
|
||||
statusNames: Record<string, string>;
|
||||
} | {
|
||||
errors: string[];
|
||||
};
|
||||
@@ -128,16 +126,12 @@ export const gitRepoLoader: LoaderFunction = async ({ params }): Promise<GitRepo
|
||||
|
||||
setGitVCS(vcs);
|
||||
|
||||
const { changes, statusNames } = await getGitChanges(vcs, workspace);
|
||||
|
||||
return {
|
||||
branch: await vcs.getBranch(),
|
||||
log: await vcs.log() || [],
|
||||
branches: await vcs.listBranches(),
|
||||
remoteBranches: await vcs.listRemoteBranches(),
|
||||
gitRepository: gitRepository,
|
||||
changes,
|
||||
statusNames,
|
||||
};
|
||||
} catch (e) {
|
||||
const errorMessage = e instanceof Error ? e.message : 'Error while fetching git repository.';
|
||||
@@ -231,15 +225,13 @@ export const cloneGitRepoAction: ActionFunction = async ({
|
||||
oauth2format,
|
||||
};
|
||||
} else {
|
||||
const password = formData.get('password');
|
||||
invariant(typeof password === 'string', 'Password is required');
|
||||
const token = formData.get('token');
|
||||
invariant(typeof token === 'string', 'Token is required');
|
||||
const username = formData.get('username');
|
||||
invariant(typeof username === 'string', 'Username is required');
|
||||
|
||||
repoSettingsPatch.credentials = {
|
||||
password,
|
||||
password: token,
|
||||
username,
|
||||
};
|
||||
}
|
||||
@@ -635,8 +627,16 @@ export const checkoutGitBranchAction: ActionFunction = async ({
|
||||
|
||||
const vcs = getGitVCS();
|
||||
|
||||
try {
|
||||
await vcs.fetch(false, 1, repo?.credentials);
|
||||
} catch (e) {
|
||||
console.warn('Error fetching from remote');
|
||||
}
|
||||
const bufferId = await database.bufferChanges();
|
||||
try {
|
||||
await vcs.checkout(branch);
|
||||
// Fetch the last 20 commits for the branch
|
||||
await vcs.fetch(true, 20, repo?.credentials);
|
||||
} catch (err) {
|
||||
const errorMessage = err instanceof Error ? err.message : err;
|
||||
return {
|
||||
@@ -644,6 +644,21 @@ export const checkoutGitBranchAction: ActionFunction = async ({
|
||||
};
|
||||
}
|
||||
|
||||
if (workspaceMeta) {
|
||||
const log = (await vcs.log()) || [];
|
||||
|
||||
const author = log[0] ? log[0].commit.author : null;
|
||||
const cachedGitLastCommitTime = author ? author.timestamp * 1000 : null;
|
||||
|
||||
await models.workspaceMeta.update(workspaceMeta, {
|
||||
cachedGitLastCommitTime,
|
||||
cachedGitRepositoryBranch: branch,
|
||||
cachedGitLastAuthor: author?.name || null,
|
||||
});
|
||||
}
|
||||
|
||||
await database.flushChanges(bufferId);
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
@@ -828,6 +843,13 @@ export const pullFromGitRemoteAction: ActionFunction = async ({
|
||||
const bufferId = await database.bufferChanges();
|
||||
|
||||
const providerName = getOauth2FormatName(gitRepository.credentials);
|
||||
|
||||
try {
|
||||
await vcs.fetch(false, 1, gitRepository?.credentials);
|
||||
} catch (e) {
|
||||
console.warn('Error fetching from remote');
|
||||
}
|
||||
|
||||
try {
|
||||
await vcs.pull(gitRepository.credentials);
|
||||
trackSegmentEvent(SegmentEvent.vcsAction, { ...vcsSegmentEventProperties('git', 'pull'), providerName });
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import { LoaderFunction } from 'react-router-dom';
|
||||
import React from 'react';
|
||||
import { LoaderFunction, Outlet, useLoaderData } from 'react-router-dom';
|
||||
|
||||
import { database } from '../../common/database';
|
||||
import * as models from '../../models';
|
||||
import { GitRepository } from '../../models/git-repository';
|
||||
import { Project } from '../../models/project';
|
||||
import { Workspace } from '../../models/workspace';
|
||||
import { WorkspaceMeta } from '../../models/workspace-meta';
|
||||
import { invariant } from '../../utils/invariant';
|
||||
|
||||
export interface WorkspaceLoaderData {
|
||||
activeWorkspace: Workspace;
|
||||
activeWorkspaceMeta?: WorkspaceMeta;
|
||||
activeProject: Project;
|
||||
gitRepository: GitRepository | null;
|
||||
}
|
||||
@@ -44,5 +47,14 @@ export const workspaceLoader: LoaderFunction = async ({
|
||||
activeWorkspace: workspace,
|
||||
activeProject,
|
||||
gitRepository,
|
||||
activeWorkspaceMeta: workspaceMeta,
|
||||
};
|
||||
};
|
||||
|
||||
const WorkspaceRoute = () => {
|
||||
const workspaceData = useLoaderData() as WorkspaceLoaderData;
|
||||
const branch = workspaceData.activeWorkspaceMeta?.cachedGitRepositoryBranch;
|
||||
return <Outlet key={branch} />;
|
||||
};
|
||||
|
||||
export default WorkspaceRoute;
|
||||
Reference in new issue
Block a user