Skip to content

Commit

Permalink
feat(core): add file copying functionality when creating worktree (#16)
Browse files Browse the repository at this point in the history
- Implement file copying feature for new worktree
- Add configuration options for copyFiles and ignoreFiles
- Update createWorktreeFromInfo function to include file copying
- Create copyIgnoredFiles utility function
  • Loading branch information
jackiotyu authored Feb 22, 2025
1 parent bf140c5 commit 497c9d7
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 9 deletions.
3 changes: 2 additions & 1 deletion l10n/bundle.l10n.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,5 +120,6 @@
"Please input branch name": "请输入分支名称",
"Delete branch": "删除分支",
"The branch {0} based on {1} will be deleted": "将删除基于 {1} 的分支 {0}",
"Failed to delete branch ( {0} ), {1}": "删除分支 ( {0} ) 失败, {1}"
"Failed to delete branch ( {0} ), {1}": "删除分支 ( {0} ) 失败, {1}",
"Failed to copy files: {error}": "复制文件失败: {error}"
}
23 changes: 23 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,29 @@
"type": "boolean",
"default": false,
"description": "%config.promptDeleteBranchAfterWorktreeDeletion.description%"
},
"git-worktree-manager.worktreeCopyPatterns": {
"type": "array",
"default": [
".env",
".vscode/**",
"*.local"
],
"markdownDescription": "%config.worktreeCopyPatterns.description%"
},
"git-worktree-manager.worktreeCopyIgnores": {
"type": "array",
"default": [
"**/node_modules/**",
"**/dist/**",
"**/.git/**",
"**/.svn/**",
"**/.hg/**",
"**/CVS/**",
"**/Thumbs.db/**",
"**/.DS_Store"
],
"markdownDescription": "%config.worktreeCopyIgnores.description%"
}
}
},
Expand Down
2 changes: 2 additions & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,7 @@
"config.worktreePick.showDeleteWorktree.description": "Show the \"Delete Worktree\" button on the results of \"Find Worktree\"",
"config.branchPick.showDeleteBranch.description": "Show the \"Delete Branch\" button on the results of \"Pick Branch\"",
"config.promptDeleteBranchAfterWorktreeDeletion.description": "Prompt to delete the branch previously associated with the worktree after its deletion",
"config.worktreeCopyPatterns.description": "Glob patterns for files to be copied when creating a new worktree, referring to [glob patterns](https://code.visualstudio.com/docs/editor/glob-patterns).",
"config.worktreeCopyIgnores.description": "Glob patterns for files to be excluded when copying files to a new worktree, referring to [glob patterns](https://code.visualstudio.com/docs/editor/glob-patterns).",
"submenus.worktree-action": "Worktree Action"
}
2 changes: 2 additions & 0 deletions package.nls.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,7 @@
"config.worktreePick.showDeleteWorktree.description": "\"查找 Worktree\" 列表中展示 \"删除 worktree\" 按钮",
"config.branchPick.showDeleteBranch.description": "\"挑选分支\" 列表中展示 \"删除分支\" 按钮",
"config.promptDeleteBranchAfterWorktreeDeletion.description": "在删除 worktree 之后,是否提示删除之前关联的分支",
"config.worktreeCopyPatterns.description": "创建新 worktree 时需要复制的文件匹配模式,参考[glob patterns介绍](https://juejin.cn/post/7474119575574855717)",
"config.worktreeCopyIgnores.description": "创建新 worktree 时需要排除的文件匹配模式,参考[glob patterns介绍](https://juejin.cn/post/7474119575574855717)",
"submenus.worktree-action": "worktree 操作"
}
20 changes: 12 additions & 8 deletions src/core/command/createWorktreeFromInfo.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import * as vscode from 'vscode';
import { addWorktree } from '@/core/git/addWorktree';
import { getMainFolder } from '@/core/git/getMainFolder';
import { confirmModal } from '@/core/ui/modal';
import { copyWorktreeFiles } from '@/core/util/copyWorktreeFiles';
import type { ICreateWorktreeInfo } from '@/types';

export const createWorktreeFromInfo = async (info: {
folderPath: string;
name: string;
label: string;
isBranch: boolean;
cwd?: string;
}) => {
export async function createWorktreeFromInfo(info: ICreateWorktreeInfo) {
const { folderPath, name, label, isBranch, cwd } = info;
let confirmCreate = await confirmModal(
vscode.l10n.t('Create worktree'),
Expand All @@ -21,6 +18,13 @@ export const createWorktreeFromInfo = async (info: {
if (!created) {
return;
}

const mainFolder = await getMainFolder(folderPath);
// Copy files after worktree creation is successful
if (mainFolder) {
await copyWorktreeFiles(mainFolder, folderPath);
}

let confirmOpen = await confirmModal(
vscode.l10n.t('Open folder'),
vscode.l10n.t('Whether to open the new worktree in a new window?'),
Expand All @@ -32,4 +36,4 @@ export const createWorktreeFromInfo = async (info: {
vscode.commands.executeCommand('vscode.openFolder', folderUri, {
forceNewWindow: true,
});
};
}
2 changes: 2 additions & 0 deletions src/core/config/setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export class Config {
static get(key: 'httpProxy', defaultValue: ''): string;
static get(key: 'workspacePathFormat', defaultValue: '$BASE_NAME - $FULL_PATH'): string;
static get(key: 'promptDeleteBranchAfterWorktreeDeletion', defaultValue: false): boolean;
static get(key: 'worktreeCopyPatterns', defaultValue: []): string[];
static get(key: 'worktreeCopyIgnores', defaultValue: []): string[];
static get<T>(key: string, defaultValue: T): T {
return vscode.workspace.getConfiguration(APP_NAME).get(key, defaultValue);
}
Expand Down
39 changes: 39 additions & 0 deletions src/core/util/copyWorktreeFiles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as vscode from 'vscode';
import path from 'path';
import fs from 'fs/promises';
import { pipeline } from 'stream/promises';
import { createReadStream, createWriteStream } from 'fs';
import { Config } from '@/core/config/setting';

export async function copyWorktreeFiles(sourceRepo: string, targetWorktree: string) {
try {
const patterns = Config.get('worktreeCopyPatterns', []);
const ignorePatterns = Config.get('worktreeCopyIgnores', []);

if (patterns.length === 0) return;

// Find matching files
const files = await vscode.workspace.findFiles(
new vscode.RelativePattern(sourceRepo, `{${patterns.join(',')}}`),
`{${ignorePatterns.join(',')}}`,
);

// Copy the found files
for (const file of files) {
const relativePath = path.relative(sourceRepo, file.fsPath);
const targetPath = path.join(targetWorktree, relativePath);
const targetDir = path.dirname(targetPath);

// Ensure target directory exists
await fs.mkdir(targetDir, { recursive: true });

// Copy single file
await pipeline(
createReadStream(file.fsPath),
createWriteStream(targetPath)
);
}
} catch (error: any) {
vscode.window.showErrorMessage(vscode.l10n.t('Failed to copy files: {error}', { error }));
}
}
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,11 @@ export type IPickBranchParams = {
showCreate: boolean;
};
export type IPickBranch = (params: IPickBranchParams) => Promise<IPickBranchResolveValue>;

export interface ICreateWorktreeInfo {
folderPath: string;
name: string;
label: string;
isBranch: boolean;
cwd?: string;
}

0 comments on commit 497c9d7

Please sign in to comment.