@ogpoyraz/wtx 0.8.2 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +68 -3
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -27971,7 +27971,7 @@ function App({ opts }) {
|
|
|
27971
27971
|
`Branch will be renamed and the checkout moved to:`,
|
|
27972
27972
|
getWorktreePathFor(modal.row.repoName, modal.to),
|
|
27973
27973
|
"",
|
|
27974
|
-
"
|
|
27974
|
+
"Uncommitted changes and synced files move with it.",
|
|
27975
27975
|
"Proceed?"
|
|
27976
27976
|
].join(`
|
|
27977
27977
|
`)
|
|
@@ -31982,6 +31982,27 @@ async function getUpstream(wtPath) {
|
|
|
31982
31982
|
return null;
|
|
31983
31983
|
}
|
|
31984
31984
|
}
|
|
31985
|
+
async function getDirtyEntries(wtPath) {
|
|
31986
|
+
try {
|
|
31987
|
+
const out = await gitExec(["-C", wtPath, "status", "--porcelain"], {});
|
|
31988
|
+
return out.split(`
|
|
31989
|
+
`).map((line) => line.trimEnd()).filter((line) => line.length > 0);
|
|
31990
|
+
} catch {
|
|
31991
|
+
return [];
|
|
31992
|
+
}
|
|
31993
|
+
}
|
|
31994
|
+
function touchesEntry(porcelainLine, entry) {
|
|
31995
|
+
const entryPath = porcelainLine.slice(3);
|
|
31996
|
+
return entryPath === entry || entryPath.startsWith(`${entry}/`);
|
|
31997
|
+
}
|
|
31998
|
+
async function isTrackedInWorktree(wtPath, entry) {
|
|
31999
|
+
try {
|
|
32000
|
+
await gitExec(["-C", wtPath, "ls-files", "--error-unmatch", "--", entry], {});
|
|
32001
|
+
return true;
|
|
32002
|
+
} catch {
|
|
32003
|
+
return false;
|
|
32004
|
+
}
|
|
32005
|
+
}
|
|
31985
32006
|
async function planRename(repo, oldBranch, newBranch, opts) {
|
|
31986
32007
|
const list = await getWorktreeList(repo.mainPath);
|
|
31987
32008
|
const candidatePath = getWorktreePath(repo, oldBranch);
|
|
@@ -32005,6 +32026,7 @@ async function renameWorktree(params) {
|
|
|
32005
32026
|
const { repo, oldBranch, newBranch, opts } = params;
|
|
32006
32027
|
const planned = await planRename(repo, oldBranch, newBranch, opts);
|
|
32007
32028
|
const cleanedDirs = [];
|
|
32029
|
+
const dirtyBefore = await getDirtyEntries(planned.worktreePath);
|
|
32008
32030
|
if (opts.dryRun) {
|
|
32009
32031
|
return {
|
|
32010
32032
|
oldBranch,
|
|
@@ -32012,7 +32034,11 @@ async function renameWorktree(params) {
|
|
|
32012
32034
|
oldPath: planned.worktreePath,
|
|
32013
32035
|
newPath: planned.newPath,
|
|
32014
32036
|
upstream: planned.upstream,
|
|
32015
|
-
cleanedDirs
|
|
32037
|
+
cleanedDirs,
|
|
32038
|
+
dirtyFiles: dirtyBefore,
|
|
32039
|
+
lostDirtyFiles: [],
|
|
32040
|
+
resyncedFiles: [],
|
|
32041
|
+
keptLocalSyncFiles: []
|
|
32016
32042
|
};
|
|
32017
32043
|
}
|
|
32018
32044
|
await gitExec(["-C", planned.worktreePath, "branch", "-m", oldBranch, newBranch], opts);
|
|
@@ -32030,13 +32056,40 @@ async function renameWorktree(params) {
|
|
|
32030
32056
|
for (const dir of cleanupEmptyParents(repo.wtRoot, repo.mainPath, planned.worktreePath)) {
|
|
32031
32057
|
cleanedDirs.push(dir);
|
|
32032
32058
|
}
|
|
32059
|
+
const dirtyAfter = await getDirtyEntries(planned.newPath);
|
|
32060
|
+
const lostDirtyFiles = dirtyBefore.filter((line) => !dirtyAfter.includes(line));
|
|
32061
|
+
const resyncedFiles = [];
|
|
32062
|
+
const keptLocalSyncFiles = [];
|
|
32063
|
+
for (const entry of repo.config.sync_files ?? []) {
|
|
32064
|
+
if (!fs28.existsSync(path33.join(repo.mainPath, entry)))
|
|
32065
|
+
continue;
|
|
32066
|
+
const destPath = path33.join(planned.newPath, entry);
|
|
32067
|
+
if (!fs28.existsSync(destPath)) {
|
|
32068
|
+
if (syncEntry(repo.mainPath, planned.newPath, entry)) {
|
|
32069
|
+
resyncedFiles.push(entry);
|
|
32070
|
+
}
|
|
32071
|
+
continue;
|
|
32072
|
+
}
|
|
32073
|
+
const tracked = await isTrackedInWorktree(planned.newPath, entry);
|
|
32074
|
+
if (tracked && !dirtyAfter.some((line) => touchesEntry(line, entry))) {
|
|
32075
|
+
if (syncEntry(repo.mainPath, planned.newPath, entry)) {
|
|
32076
|
+
resyncedFiles.push(entry);
|
|
32077
|
+
}
|
|
32078
|
+
continue;
|
|
32079
|
+
}
|
|
32080
|
+
keptLocalSyncFiles.push(entry);
|
|
32081
|
+
}
|
|
32033
32082
|
return {
|
|
32034
32083
|
oldBranch,
|
|
32035
32084
|
newBranch,
|
|
32036
32085
|
oldPath: planned.worktreePath,
|
|
32037
32086
|
newPath: planned.newPath,
|
|
32038
32087
|
upstream: planned.upstream,
|
|
32039
|
-
cleanedDirs
|
|
32088
|
+
cleanedDirs,
|
|
32089
|
+
dirtyFiles: dirtyAfter,
|
|
32090
|
+
lostDirtyFiles,
|
|
32091
|
+
resyncedFiles,
|
|
32092
|
+
keptLocalSyncFiles
|
|
32040
32093
|
};
|
|
32041
32094
|
}
|
|
32042
32095
|
|
|
@@ -32082,6 +32135,18 @@ function registerRenameCommand(program2) {
|
|
|
32082
32135
|
stepSuccess("Cleaned up empty directory", path34.relative(repo.wtRoot, dir) + "/");
|
|
32083
32136
|
}
|
|
32084
32137
|
stepSuccess("Renamed", `${outcome.oldPath} → ${outcome.newPath}`);
|
|
32138
|
+
if (outcome.dirtyFiles.length > 0) {
|
|
32139
|
+
stepSuccess("Carried uncommitted files", `${outcome.dirtyFiles.length} entr${outcome.dirtyFiles.length === 1 ? "y" : "ies"} moved with the checkout`);
|
|
32140
|
+
}
|
|
32141
|
+
if (outcome.lostDirtyFiles.length > 0) {
|
|
32142
|
+
stepError("Uncommitted changes missing after rename", outcome.lostDirtyFiles.join(", "));
|
|
32143
|
+
}
|
|
32144
|
+
if (outcome.resyncedFiles.length > 0) {
|
|
32145
|
+
stepSuccess("Synced files", outcome.resyncedFiles.join(", "));
|
|
32146
|
+
}
|
|
32147
|
+
for (const entry of outcome.keptLocalSyncFiles) {
|
|
32148
|
+
indented(`Kept local version of ${entry} — it has uncommitted edits`);
|
|
32149
|
+
}
|
|
32085
32150
|
if (outcome.upstream) {
|
|
32086
32151
|
indented(`Upstream still tracks '${outcome.upstream}' — after pushing run: git push -u origin ${newBranch}`);
|
|
32087
32152
|
}
|