Add branch creation and file history search
Implement the ability to create new local branches directly from the application's UI. This includes a new backend command to handle branch creation with validation and a frontend form in the branch panel. Additionally, extend the global search dialog to include a "Files" tab. Users can now search for files by name or path within the repository. Selecting a file in the search results displays its full commit history, with options to diff the file at a specific commit or restore it to that version.
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
commit,
|
||||
compareCommits,
|
||||
cancelCodeSearch,
|
||||
createBranch,
|
||||
diffFileAgainstWorkingTree,
|
||||
compareFileToParent,
|
||||
getStatus,
|
||||
@@ -413,6 +414,18 @@
|
||||
});
|
||||
}
|
||||
|
||||
async function createNewBranch(branchName: string) {
|
||||
const name = branchName.trim();
|
||||
if (!activeRepoPath || !name) return;
|
||||
await runOperation(`Creating ${name}`, async () => {
|
||||
applyStatus(await createBranch(activeRepoPath, name));
|
||||
await refreshBranchList(activeRepoPath);
|
||||
await refreshCommitHistory(activeRepoPath);
|
||||
await refreshExplorerFiles(activeRepoPath);
|
||||
await refreshFileHistory(activeRepoPath);
|
||||
});
|
||||
}
|
||||
|
||||
async function merge(branch: GitBranchInfo) {
|
||||
if (!activeRepoPath || branch.current) return;
|
||||
await runOperation(`Merging ${branch.name}`, async () => {
|
||||
@@ -719,6 +732,17 @@
|
||||
expandedExplorerPaths = new Set();
|
||||
}
|
||||
|
||||
function explorerParentFolders(path: string): string[] {
|
||||
const parts = normalizeExplorerPath(path).split("/").filter(Boolean);
|
||||
const folders: string[] = [];
|
||||
let current = "";
|
||||
for (let index = 0; index < parts.length - 1; index++) {
|
||||
current = current ? `${current}/${parts[index]}` : parts[index];
|
||||
folders.push(current);
|
||||
}
|
||||
return folders;
|
||||
}
|
||||
|
||||
async function selectExplorerNode(node: ExplorerNode) {
|
||||
if (!activeRepoPath || (selectedExplorerPath === node.path && selectedExplorerKind === node.kind)) return;
|
||||
selectedExplorerPath = node.path;
|
||||
@@ -728,6 +752,17 @@
|
||||
});
|
||||
}
|
||||
|
||||
async function selectFileFromSearch(file: GitRepositoryFile) {
|
||||
if (!activeRepoPath) return;
|
||||
selectedExplorerPath = file.path;
|
||||
selectedExplorerKind = "file";
|
||||
expandedExplorerPaths = new Set([...expandedExplorerPaths, ...explorerParentFolders(file.path)]);
|
||||
|
||||
await runOperation(`Loading ${file.path} history`, async () => {
|
||||
await refreshFileHistory(activeRepoPath, file.path);
|
||||
});
|
||||
}
|
||||
|
||||
async function restoreSelectedFileFromCommit(target: GitCommit) {
|
||||
if (!activeRepoPath || !selectedExplorerPath) return;
|
||||
const kind = selectedExplorerKind === "folder" ? "folder" : "file";
|
||||
@@ -1009,6 +1044,7 @@
|
||||
{isBusy}
|
||||
onCheckout={checkout}
|
||||
onMerge={merge}
|
||||
onCreateBranch={createNewBranch}
|
||||
/>
|
||||
<ExplorerPanel
|
||||
{repoFiles}
|
||||
@@ -1133,10 +1169,16 @@
|
||||
isSearching={globalSearchBusy}
|
||||
error={globalSearchError}
|
||||
results={globalSearchResults}
|
||||
files={repoFiles}
|
||||
fileHistory={fileHistory}
|
||||
selectedFilePath={selectedExplorerPath}
|
||||
onClose={closeGlobalSearchDialog}
|
||||
onSearch={runGlobalSearch}
|
||||
onCancel={cancelGlobalSearch}
|
||||
onDiff={diffSearchHit}
|
||||
onSelectFile={selectFileFromSearch}
|
||||
onFileHistoryDiff={diffSelectedFileFromCommit}
|
||||
onFileHistoryRestore={restoreSelectedFileFromCommit}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user