@bretwardjames/ghp-core 0.2.0-beta.0 → 0.2.0-beta.2
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/index.cjs +143 -3
- package/dist/index.d.cts +67 -2
- package/dist/index.d.ts +67 -2
- package/dist/index.js +135 -2
- package/package.json +8 -7
package/dist/index.cjs
CHANGED
|
@@ -36,10 +36,13 @@ __export(index_exports, {
|
|
|
36
36
|
checkoutBranch: () => checkoutBranch,
|
|
37
37
|
computeSettingsDiff: () => computeSettingsDiff,
|
|
38
38
|
createBranch: () => createBranch,
|
|
39
|
+
createWorktree: () => createWorktree,
|
|
39
40
|
detectRepository: () => detectRepository,
|
|
41
|
+
extractIssueNumberFromBranch: () => extractIssueNumberFromBranch,
|
|
40
42
|
fetchOrigin: () => fetchOrigin,
|
|
41
43
|
formatConflict: () => formatConflict,
|
|
42
44
|
generateBranchName: () => generateBranchName,
|
|
45
|
+
generateWorktreePath: () => generateWorktreePath,
|
|
43
46
|
getAllBranches: () => getAllBranches,
|
|
44
47
|
getCommitsAhead: () => getCommitsAhead,
|
|
45
48
|
getCommitsBehind: () => getCommitsBehind,
|
|
@@ -49,9 +52,11 @@ __export(index_exports, {
|
|
|
49
52
|
getLocalBranches: () => getLocalBranches,
|
|
50
53
|
getRemoteBranches: () => getRemoteBranches,
|
|
51
54
|
getRepositoryRoot: () => getRepositoryRoot,
|
|
55
|
+
getWorktreeForBranch: () => getWorktreeForBranch,
|
|
52
56
|
hasDifferences: () => hasDifferences,
|
|
53
57
|
hasUncommittedChanges: () => hasUncommittedChanges,
|
|
54
58
|
isGitRepository: () => isGitRepository,
|
|
59
|
+
listWorktrees: () => listWorktrees,
|
|
55
60
|
normalizeVSCodeSettings: () => normalizeVSCodeSettings,
|
|
56
61
|
parseBranchLink: () => parseBranchLink,
|
|
57
62
|
parseGitHubUrl: () => parseGitHubUrl,
|
|
@@ -59,6 +64,7 @@ __export(index_exports, {
|
|
|
59
64
|
pullLatest: () => pullLatest,
|
|
60
65
|
queries: () => queries_exports,
|
|
61
66
|
removeBranchLinkFromBody: () => removeBranchLinkFromBody,
|
|
67
|
+
removeWorktree: () => removeWorktree,
|
|
62
68
|
resolveConflicts: () => resolveConflicts,
|
|
63
69
|
sanitizeForBranchName: () => sanitizeForBranchName,
|
|
64
70
|
setBranchLinkInBody: () => setBranchLinkInBody,
|
|
@@ -66,7 +72,8 @@ __export(index_exports, {
|
|
|
66
72
|
toVSCodeSettings: () => toVSCodeSettings,
|
|
67
73
|
useCli: () => useCli,
|
|
68
74
|
useCustom: () => useCustom,
|
|
69
|
-
useVSCode: () => useVSCode
|
|
75
|
+
useVSCode: () => useVSCode,
|
|
76
|
+
worktreeExists: () => worktreeExists
|
|
70
77
|
});
|
|
71
78
|
module.exports = __toCommonJS(index_exports);
|
|
72
79
|
|
|
@@ -405,7 +412,7 @@ var REMOVE_LABELS_MUTATION = `
|
|
|
405
412
|
var ISSUES_WITH_LABEL_QUERY = `
|
|
406
413
|
query($owner: String!, $name: String!, $labels: [String!]) {
|
|
407
414
|
repository(owner: $owner, name: $name) {
|
|
408
|
-
issues(first: 10, labels: $labels, states: [OPEN]) {
|
|
415
|
+
issues(first: 10, labels: $labels, states: [OPEN, CLOSED]) {
|
|
409
416
|
nodes {
|
|
410
417
|
number
|
|
411
418
|
}
|
|
@@ -1158,6 +1165,7 @@ var BranchLinker = class {
|
|
|
1158
1165
|
// src/git-utils.ts
|
|
1159
1166
|
var import_child_process = require("child_process");
|
|
1160
1167
|
var import_util = require("util");
|
|
1168
|
+
var import_os = require("os");
|
|
1161
1169
|
|
|
1162
1170
|
// src/url-parser.ts
|
|
1163
1171
|
function parseGitHubUrl(url) {
|
|
@@ -1210,6 +1218,28 @@ function buildOrgProjectUrl(org, projectNumber) {
|
|
|
1210
1218
|
}
|
|
1211
1219
|
|
|
1212
1220
|
// src/git-utils.ts
|
|
1221
|
+
function sanitizeForPath(input) {
|
|
1222
|
+
return String(input).replace(/\.\./g, "_").replace(/[;&|`$(){}[\]<>!]/g, "").replace(/\s+/g, "-").replace(/[^a-zA-Z0-9_\-./]/g, "_");
|
|
1223
|
+
}
|
|
1224
|
+
function validateBranchName(branch) {
|
|
1225
|
+
if (!branch || branch.trim().length === 0) {
|
|
1226
|
+
throw new Error("Branch name cannot be empty");
|
|
1227
|
+
}
|
|
1228
|
+
const dangerousChars = /[`$\\!;|&<>(){}[\]'"]/;
|
|
1229
|
+
if (dangerousChars.test(branch)) {
|
|
1230
|
+
throw new Error(`Branch name contains invalid characters: ${branch}`);
|
|
1231
|
+
}
|
|
1232
|
+
const gitInvalidChars = /[\s~^:?*\[\\]/;
|
|
1233
|
+
if (gitInvalidChars.test(branch)) {
|
|
1234
|
+
throw new Error(`Branch name contains invalid git characters: ${branch}`);
|
|
1235
|
+
}
|
|
1236
|
+
if (branch.includes("..")) {
|
|
1237
|
+
throw new Error(`Branch name cannot contain '..': ${branch}`);
|
|
1238
|
+
}
|
|
1239
|
+
if (/^[./]|[./]$/.test(branch)) {
|
|
1240
|
+
throw new Error(`Branch name cannot start or end with '/' or '.': ${branch}`);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1213
1243
|
var execAsync = (0, import_util.promisify)(import_child_process.exec);
|
|
1214
1244
|
async function execGit(command, options = {}) {
|
|
1215
1245
|
const cwd = options.cwd || process.cwd();
|
|
@@ -1311,6 +1341,25 @@ function generateBranchName(pattern, vars, maxLength = 60) {
|
|
|
1311
1341
|
}
|
|
1312
1342
|
return branch;
|
|
1313
1343
|
}
|
|
1344
|
+
function extractIssueNumberFromBranch(branchName) {
|
|
1345
|
+
const patterns = [
|
|
1346
|
+
/\/(\d+)-/,
|
|
1347
|
+
// user/123-title
|
|
1348
|
+
/^(\d+)-/,
|
|
1349
|
+
// 123-title
|
|
1350
|
+
/-(\d+)-/,
|
|
1351
|
+
// feature-123-title
|
|
1352
|
+
/[/#](\d+)$/
|
|
1353
|
+
// ends with #123 or /123
|
|
1354
|
+
];
|
|
1355
|
+
for (const pattern of patterns) {
|
|
1356
|
+
const match = branchName.match(pattern);
|
|
1357
|
+
if (match) {
|
|
1358
|
+
return parseInt(match[1], 10);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
return null;
|
|
1362
|
+
}
|
|
1314
1363
|
async function getLocalBranches(options = {}) {
|
|
1315
1364
|
try {
|
|
1316
1365
|
const { stdout } = await execGit('git branch --format="%(refname:short)"', options);
|
|
@@ -1357,6 +1406,90 @@ async function getDefaultBranch(options = {}) {
|
|
|
1357
1406
|
}
|
|
1358
1407
|
return "master";
|
|
1359
1408
|
}
|
|
1409
|
+
function validatePath(path) {
|
|
1410
|
+
if (!path || path.trim().length === 0) {
|
|
1411
|
+
throw new Error("Path cannot be empty");
|
|
1412
|
+
}
|
|
1413
|
+
const dangerousChars = /[`$;|&<>(){}[\]'"\n\r]/;
|
|
1414
|
+
if (dangerousChars.test(path)) {
|
|
1415
|
+
throw new Error(`Path contains invalid characters: ${path}`);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
async function createWorktree(worktreePath, branch, options = {}) {
|
|
1419
|
+
validateBranchName(branch);
|
|
1420
|
+
validatePath(worktreePath);
|
|
1421
|
+
const localExists = await branchExists(branch, options);
|
|
1422
|
+
if (localExists) {
|
|
1423
|
+
await execGit(`git worktree add "${worktreePath}" "${branch}"`, options);
|
|
1424
|
+
} else {
|
|
1425
|
+
try {
|
|
1426
|
+
await execGit(`git worktree add "${worktreePath}" -b "${branch}" "origin/${branch}"`, options);
|
|
1427
|
+
} catch {
|
|
1428
|
+
await execGit(`git worktree add -b "${branch}" "${worktreePath}"`, options);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
async function removeWorktree(worktreePath, options = {}, force = false) {
|
|
1433
|
+
validatePath(worktreePath);
|
|
1434
|
+
const forceFlag = force ? "--force" : "";
|
|
1435
|
+
await execGit(`git worktree remove ${forceFlag} "${worktreePath}"`, options);
|
|
1436
|
+
}
|
|
1437
|
+
async function listWorktrees(options = {}) {
|
|
1438
|
+
try {
|
|
1439
|
+
const { stdout } = await execGit("git worktree list --porcelain", options);
|
|
1440
|
+
const worktrees = [];
|
|
1441
|
+
const entries = stdout.trim().split("\n\n");
|
|
1442
|
+
for (const entry of entries) {
|
|
1443
|
+
if (!entry.trim()) continue;
|
|
1444
|
+
const lines = entry.split("\n");
|
|
1445
|
+
const info = {
|
|
1446
|
+
isMain: false,
|
|
1447
|
+
branch: null
|
|
1448
|
+
};
|
|
1449
|
+
for (const line of lines) {
|
|
1450
|
+
if (line.startsWith("worktree ")) {
|
|
1451
|
+
info.path = line.substring(9);
|
|
1452
|
+
} else if (line.startsWith("HEAD ")) {
|
|
1453
|
+
info.head = line.substring(5);
|
|
1454
|
+
} else if (line.startsWith("branch ")) {
|
|
1455
|
+
info.branch = line.substring(7).replace(/^refs\/heads\//, "");
|
|
1456
|
+
} else if (line === "bare") {
|
|
1457
|
+
info.isMain = true;
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
if (worktrees.length === 0) {
|
|
1461
|
+
info.isMain = true;
|
|
1462
|
+
}
|
|
1463
|
+
if (info.path && info.head) {
|
|
1464
|
+
worktrees.push(info);
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
return worktrees;
|
|
1468
|
+
} catch {
|
|
1469
|
+
return [];
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
async function getWorktreeForBranch(branch, options = {}) {
|
|
1473
|
+
const worktrees = await listWorktrees(options);
|
|
1474
|
+
return worktrees.find((wt) => wt.branch === branch) || null;
|
|
1475
|
+
}
|
|
1476
|
+
async function worktreeExists(worktreePath, options = {}) {
|
|
1477
|
+
const worktrees = await listWorktrees(options);
|
|
1478
|
+
return worktrees.some((wt) => wt.path === worktreePath);
|
|
1479
|
+
}
|
|
1480
|
+
function generateWorktreePath(basePath, repoName, identifier, title) {
|
|
1481
|
+
const safeRepoName = sanitizeForPath(repoName);
|
|
1482
|
+
let dirName;
|
|
1483
|
+
if (title && typeof identifier === "number") {
|
|
1484
|
+
const titleSlug = sanitizeForBranchName(title).substring(0, 35).replace(/-$/, "");
|
|
1485
|
+
dirName = `${identifier}-${titleSlug}`;
|
|
1486
|
+
} else {
|
|
1487
|
+
dirName = sanitizeForPath(String(identifier));
|
|
1488
|
+
}
|
|
1489
|
+
const expandedBase = basePath.startsWith("~") ? basePath.replace("~", (0, import_os.homedir)()) : basePath;
|
|
1490
|
+
const cleanBase = expandedBase.replace(/\/+$/, "");
|
|
1491
|
+
return `${cleanBase}/${safeRepoName}/${dirName}`;
|
|
1492
|
+
}
|
|
1360
1493
|
|
|
1361
1494
|
// src/sync.ts
|
|
1362
1495
|
var SYNCABLE_KEYS = [
|
|
@@ -1537,10 +1670,13 @@ function getDiffSummary(diff) {
|
|
|
1537
1670
|
checkoutBranch,
|
|
1538
1671
|
computeSettingsDiff,
|
|
1539
1672
|
createBranch,
|
|
1673
|
+
createWorktree,
|
|
1540
1674
|
detectRepository,
|
|
1675
|
+
extractIssueNumberFromBranch,
|
|
1541
1676
|
fetchOrigin,
|
|
1542
1677
|
formatConflict,
|
|
1543
1678
|
generateBranchName,
|
|
1679
|
+
generateWorktreePath,
|
|
1544
1680
|
getAllBranches,
|
|
1545
1681
|
getCommitsAhead,
|
|
1546
1682
|
getCommitsBehind,
|
|
@@ -1550,9 +1686,11 @@ function getDiffSummary(diff) {
|
|
|
1550
1686
|
getLocalBranches,
|
|
1551
1687
|
getRemoteBranches,
|
|
1552
1688
|
getRepositoryRoot,
|
|
1689
|
+
getWorktreeForBranch,
|
|
1553
1690
|
hasDifferences,
|
|
1554
1691
|
hasUncommittedChanges,
|
|
1555
1692
|
isGitRepository,
|
|
1693
|
+
listWorktrees,
|
|
1556
1694
|
normalizeVSCodeSettings,
|
|
1557
1695
|
parseBranchLink,
|
|
1558
1696
|
parseGitHubUrl,
|
|
@@ -1560,6 +1698,7 @@ function getDiffSummary(diff) {
|
|
|
1560
1698
|
pullLatest,
|
|
1561
1699
|
queries,
|
|
1562
1700
|
removeBranchLinkFromBody,
|
|
1701
|
+
removeWorktree,
|
|
1563
1702
|
resolveConflicts,
|
|
1564
1703
|
sanitizeForBranchName,
|
|
1565
1704
|
setBranchLinkInBody,
|
|
@@ -1567,5 +1706,6 @@ function getDiffSummary(diff) {
|
|
|
1567
1706
|
toVSCodeSettings,
|
|
1568
1707
|
useCli,
|
|
1569
1708
|
useCustom,
|
|
1570
|
-
useVSCode
|
|
1709
|
+
useVSCode,
|
|
1710
|
+
worktreeExists
|
|
1571
1711
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -629,6 +629,16 @@ declare function generateBranchName(pattern: string, vars: {
|
|
|
629
629
|
title: string;
|
|
630
630
|
repo: string;
|
|
631
631
|
}, maxLength?: number): string;
|
|
632
|
+
/**
|
|
633
|
+
* Extract issue number from a branch name.
|
|
634
|
+
* Supports common patterns:
|
|
635
|
+
* - user/123-feature-name
|
|
636
|
+
* - feature/123-something
|
|
637
|
+
* - 123-fix-bug
|
|
638
|
+
* - fix-123-something
|
|
639
|
+
* - ends with #123 or /123
|
|
640
|
+
*/
|
|
641
|
+
declare function extractIssueNumberFromBranch(branchName: string): number | null;
|
|
632
642
|
/**
|
|
633
643
|
* Get all local branches
|
|
634
644
|
*/
|
|
@@ -645,6 +655,61 @@ declare function getAllBranches(options?: GitOptions): Promise<string[]>;
|
|
|
645
655
|
* Get the default branch name (main or master)
|
|
646
656
|
*/
|
|
647
657
|
declare function getDefaultBranch(options?: GitOptions): Promise<string>;
|
|
658
|
+
/**
|
|
659
|
+
* Information about a git worktree
|
|
660
|
+
*/
|
|
661
|
+
interface WorktreeInfo {
|
|
662
|
+
/** Absolute path to the worktree directory */
|
|
663
|
+
path: string;
|
|
664
|
+
/** Commit SHA the worktree is at */
|
|
665
|
+
head: string;
|
|
666
|
+
/** Branch name (without refs/heads/ prefix), or null if detached */
|
|
667
|
+
branch: string | null;
|
|
668
|
+
/** Whether this is the main worktree (the original repo) */
|
|
669
|
+
isMain: boolean;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Create a new worktree for a branch
|
|
673
|
+
* @param worktreePath - Path where the worktree will be created
|
|
674
|
+
* @param branch - Branch to checkout in the worktree
|
|
675
|
+
* @param options - Git options (cwd determines the source repository)
|
|
676
|
+
*/
|
|
677
|
+
declare function createWorktree(worktreePath: string, branch: string, options?: GitOptions): Promise<void>;
|
|
678
|
+
/**
|
|
679
|
+
* Remove a worktree
|
|
680
|
+
* @param worktreePath - Path to the worktree to remove
|
|
681
|
+
* @param options - Git options
|
|
682
|
+
* @param force - Force removal even if worktree has uncommitted changes
|
|
683
|
+
*/
|
|
684
|
+
declare function removeWorktree(worktreePath: string, options?: GitOptions, force?: boolean): Promise<void>;
|
|
685
|
+
/**
|
|
686
|
+
* List all worktrees for the repository
|
|
687
|
+
* @param options - Git options
|
|
688
|
+
* @returns Array of worktree information
|
|
689
|
+
*/
|
|
690
|
+
declare function listWorktrees(options?: GitOptions): Promise<WorktreeInfo[]>;
|
|
691
|
+
/**
|
|
692
|
+
* Get worktree for a specific branch
|
|
693
|
+
* @param branch - Branch name to find
|
|
694
|
+
* @param options - Git options
|
|
695
|
+
* @returns Worktree info if found, null otherwise
|
|
696
|
+
*/
|
|
697
|
+
declare function getWorktreeForBranch(branch: string, options?: GitOptions): Promise<WorktreeInfo | null>;
|
|
698
|
+
/**
|
|
699
|
+
* Check if a worktree exists at the given path
|
|
700
|
+
* @param worktreePath - Path to check
|
|
701
|
+
* @param options - Git options
|
|
702
|
+
*/
|
|
703
|
+
declare function worktreeExists(worktreePath: string, options?: GitOptions): Promise<boolean>;
|
|
704
|
+
/**
|
|
705
|
+
* Generate a worktree path based on repo and issue info
|
|
706
|
+
* @param basePath - Base directory for worktrees (e.g., ~/.ghp/worktrees)
|
|
707
|
+
* @param repoName - Repository name
|
|
708
|
+
* @param identifier - Issue number or branch name to use as identifier
|
|
709
|
+
* @param title - Optional title to create a descriptive directory name (e.g., "123-fix-auth-bug")
|
|
710
|
+
* @returns Full path to the worktree directory
|
|
711
|
+
*/
|
|
712
|
+
declare function generateWorktreePath(basePath: string, repoName: string, identifier: string | number, title?: string): string;
|
|
648
713
|
|
|
649
714
|
/**
|
|
650
715
|
* URL parsing utilities for GitHub repositories and issues.
|
|
@@ -937,7 +1002,7 @@ declare const REMOVE_LABELS_MUTATION = "\n mutation($issueId: ID!, $labelIds:
|
|
|
937
1002
|
/**
|
|
938
1003
|
* Query to find issues with a specific label
|
|
939
1004
|
*/
|
|
940
|
-
declare const ISSUES_WITH_LABEL_QUERY = "\n query($owner: String!, $name: String!, $labels: [String!]) {\n repository(owner: $owner, name: $name) {\n issues(first: 10, labels: $labels, states: [OPEN]) {\n nodes {\n number\n }\n }\n }\n }\n";
|
|
1005
|
+
declare const ISSUES_WITH_LABEL_QUERY = "\n query($owner: String!, $name: String!, $labels: [String!]) {\n repository(owner: $owner, name: $name) {\n issues(first: 10, labels: $labels, states: [OPEN, CLOSED]) {\n nodes {\n number\n }\n }\n }\n }\n";
|
|
941
1006
|
/**
|
|
942
1007
|
* Query to get available issue types for a repository
|
|
943
1008
|
*/
|
|
@@ -988,4 +1053,4 @@ declare namespace queries {
|
|
|
988
1053
|
export { queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
|
|
989
1054
|
}
|
|
990
1055
|
|
|
991
|
-
export { type AssigneeInfo, type AuthError, BranchLinker, CLI_TO_VSCODE_MAP, type Collaborator, type ConflictChoices, type ConflictResolution, DEFAULT_VALUES, type DateFieldValue, type FieldInfo, type FieldValue, type FieldValueConnection, GitHubAPI, type GitHubAPIOptions, type GitOptions, type IssueDetails, type IssueReference, type IterationFieldValue, type LabelInfo, type NumberFieldValue, type Project, type ProjectConfig, type ProjectItem, type ProjectItemContent, type ProjectItemsQueryResponse, type ProjectV2, type ProjectV2Field, type ProjectV2Item, type ProjectV2View, type ProjectWithViews, type ProjectsQueryResponse, type RepoInfo, type ResolvedSettings, SETTING_DISPLAY_NAMES, SYNCABLE_KEYS, type SettingConflict, type SettingsDiff, type SettingsSource, type SingleSelectFieldValue, type StatusField, type SyncableSettingKey, type SyncableSettings, type TextFieldValue, type TokenProvider, VSCODE_TO_CLI_MAP, branchExists, buildIssueUrl, buildOrgProjectUrl, buildProjectUrl, buildPullRequestUrl, buildRepoUrl, checkoutBranch, computeSettingsDiff, createBranch, detectRepository, fetchOrigin, formatConflict, generateBranchName, getAllBranches, getCommitsAhead, getCommitsBehind, getCurrentBranch, getDefaultBranch, getDiffSummary, getLocalBranches, getRemoteBranches, getRepositoryRoot, hasDifferences, hasUncommittedChanges, isGitRepository, normalizeVSCodeSettings, parseBranchLink, parseGitHubUrl, parseIssueUrl, pullLatest, queries, removeBranchLinkFromBody, resolveConflicts, sanitizeForBranchName, setBranchLinkInBody, skip, toVSCodeSettings, useCli, useCustom, useVSCode };
|
|
1056
|
+
export { type AssigneeInfo, type AuthError, BranchLinker, CLI_TO_VSCODE_MAP, type Collaborator, type ConflictChoices, type ConflictResolution, DEFAULT_VALUES, type DateFieldValue, type FieldInfo, type FieldValue, type FieldValueConnection, GitHubAPI, type GitHubAPIOptions, type GitOptions, type IssueDetails, type IssueReference, type IterationFieldValue, type LabelInfo, type NumberFieldValue, type Project, type ProjectConfig, type ProjectItem, type ProjectItemContent, type ProjectItemsQueryResponse, type ProjectV2, type ProjectV2Field, type ProjectV2Item, type ProjectV2View, type ProjectWithViews, type ProjectsQueryResponse, type RepoInfo, type ResolvedSettings, SETTING_DISPLAY_NAMES, SYNCABLE_KEYS, type SettingConflict, type SettingsDiff, type SettingsSource, type SingleSelectFieldValue, type StatusField, type SyncableSettingKey, type SyncableSettings, type TextFieldValue, type TokenProvider, VSCODE_TO_CLI_MAP, type WorktreeInfo, branchExists, buildIssueUrl, buildOrgProjectUrl, buildProjectUrl, buildPullRequestUrl, buildRepoUrl, checkoutBranch, computeSettingsDiff, createBranch, createWorktree, detectRepository, extractIssueNumberFromBranch, fetchOrigin, formatConflict, generateBranchName, generateWorktreePath, getAllBranches, getCommitsAhead, getCommitsBehind, getCurrentBranch, getDefaultBranch, getDiffSummary, getLocalBranches, getRemoteBranches, getRepositoryRoot, getWorktreeForBranch, hasDifferences, hasUncommittedChanges, isGitRepository, listWorktrees, normalizeVSCodeSettings, parseBranchLink, parseGitHubUrl, parseIssueUrl, pullLatest, queries, removeBranchLinkFromBody, removeWorktree, resolveConflicts, sanitizeForBranchName, setBranchLinkInBody, skip, toVSCodeSettings, useCli, useCustom, useVSCode, worktreeExists };
|
package/dist/index.d.ts
CHANGED
|
@@ -629,6 +629,16 @@ declare function generateBranchName(pattern: string, vars: {
|
|
|
629
629
|
title: string;
|
|
630
630
|
repo: string;
|
|
631
631
|
}, maxLength?: number): string;
|
|
632
|
+
/**
|
|
633
|
+
* Extract issue number from a branch name.
|
|
634
|
+
* Supports common patterns:
|
|
635
|
+
* - user/123-feature-name
|
|
636
|
+
* - feature/123-something
|
|
637
|
+
* - 123-fix-bug
|
|
638
|
+
* - fix-123-something
|
|
639
|
+
* - ends with #123 or /123
|
|
640
|
+
*/
|
|
641
|
+
declare function extractIssueNumberFromBranch(branchName: string): number | null;
|
|
632
642
|
/**
|
|
633
643
|
* Get all local branches
|
|
634
644
|
*/
|
|
@@ -645,6 +655,61 @@ declare function getAllBranches(options?: GitOptions): Promise<string[]>;
|
|
|
645
655
|
* Get the default branch name (main or master)
|
|
646
656
|
*/
|
|
647
657
|
declare function getDefaultBranch(options?: GitOptions): Promise<string>;
|
|
658
|
+
/**
|
|
659
|
+
* Information about a git worktree
|
|
660
|
+
*/
|
|
661
|
+
interface WorktreeInfo {
|
|
662
|
+
/** Absolute path to the worktree directory */
|
|
663
|
+
path: string;
|
|
664
|
+
/** Commit SHA the worktree is at */
|
|
665
|
+
head: string;
|
|
666
|
+
/** Branch name (without refs/heads/ prefix), or null if detached */
|
|
667
|
+
branch: string | null;
|
|
668
|
+
/** Whether this is the main worktree (the original repo) */
|
|
669
|
+
isMain: boolean;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Create a new worktree for a branch
|
|
673
|
+
* @param worktreePath - Path where the worktree will be created
|
|
674
|
+
* @param branch - Branch to checkout in the worktree
|
|
675
|
+
* @param options - Git options (cwd determines the source repository)
|
|
676
|
+
*/
|
|
677
|
+
declare function createWorktree(worktreePath: string, branch: string, options?: GitOptions): Promise<void>;
|
|
678
|
+
/**
|
|
679
|
+
* Remove a worktree
|
|
680
|
+
* @param worktreePath - Path to the worktree to remove
|
|
681
|
+
* @param options - Git options
|
|
682
|
+
* @param force - Force removal even if worktree has uncommitted changes
|
|
683
|
+
*/
|
|
684
|
+
declare function removeWorktree(worktreePath: string, options?: GitOptions, force?: boolean): Promise<void>;
|
|
685
|
+
/**
|
|
686
|
+
* List all worktrees for the repository
|
|
687
|
+
* @param options - Git options
|
|
688
|
+
* @returns Array of worktree information
|
|
689
|
+
*/
|
|
690
|
+
declare function listWorktrees(options?: GitOptions): Promise<WorktreeInfo[]>;
|
|
691
|
+
/**
|
|
692
|
+
* Get worktree for a specific branch
|
|
693
|
+
* @param branch - Branch name to find
|
|
694
|
+
* @param options - Git options
|
|
695
|
+
* @returns Worktree info if found, null otherwise
|
|
696
|
+
*/
|
|
697
|
+
declare function getWorktreeForBranch(branch: string, options?: GitOptions): Promise<WorktreeInfo | null>;
|
|
698
|
+
/**
|
|
699
|
+
* Check if a worktree exists at the given path
|
|
700
|
+
* @param worktreePath - Path to check
|
|
701
|
+
* @param options - Git options
|
|
702
|
+
*/
|
|
703
|
+
declare function worktreeExists(worktreePath: string, options?: GitOptions): Promise<boolean>;
|
|
704
|
+
/**
|
|
705
|
+
* Generate a worktree path based on repo and issue info
|
|
706
|
+
* @param basePath - Base directory for worktrees (e.g., ~/.ghp/worktrees)
|
|
707
|
+
* @param repoName - Repository name
|
|
708
|
+
* @param identifier - Issue number or branch name to use as identifier
|
|
709
|
+
* @param title - Optional title to create a descriptive directory name (e.g., "123-fix-auth-bug")
|
|
710
|
+
* @returns Full path to the worktree directory
|
|
711
|
+
*/
|
|
712
|
+
declare function generateWorktreePath(basePath: string, repoName: string, identifier: string | number, title?: string): string;
|
|
648
713
|
|
|
649
714
|
/**
|
|
650
715
|
* URL parsing utilities for GitHub repositories and issues.
|
|
@@ -937,7 +1002,7 @@ declare const REMOVE_LABELS_MUTATION = "\n mutation($issueId: ID!, $labelIds:
|
|
|
937
1002
|
/**
|
|
938
1003
|
* Query to find issues with a specific label
|
|
939
1004
|
*/
|
|
940
|
-
declare const ISSUES_WITH_LABEL_QUERY = "\n query($owner: String!, $name: String!, $labels: [String!]) {\n repository(owner: $owner, name: $name) {\n issues(first: 10, labels: $labels, states: [OPEN]) {\n nodes {\n number\n }\n }\n }\n }\n";
|
|
1005
|
+
declare const ISSUES_WITH_LABEL_QUERY = "\n query($owner: String!, $name: String!, $labels: [String!]) {\n repository(owner: $owner, name: $name) {\n issues(first: 10, labels: $labels, states: [OPEN, CLOSED]) {\n nodes {\n number\n }\n }\n }\n }\n";
|
|
941
1006
|
/**
|
|
942
1007
|
* Query to get available issue types for a repository
|
|
943
1008
|
*/
|
|
@@ -988,4 +1053,4 @@ declare namespace queries {
|
|
|
988
1053
|
export { queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
|
|
989
1054
|
}
|
|
990
1055
|
|
|
991
|
-
export { type AssigneeInfo, type AuthError, BranchLinker, CLI_TO_VSCODE_MAP, type Collaborator, type ConflictChoices, type ConflictResolution, DEFAULT_VALUES, type DateFieldValue, type FieldInfo, type FieldValue, type FieldValueConnection, GitHubAPI, type GitHubAPIOptions, type GitOptions, type IssueDetails, type IssueReference, type IterationFieldValue, type LabelInfo, type NumberFieldValue, type Project, type ProjectConfig, type ProjectItem, type ProjectItemContent, type ProjectItemsQueryResponse, type ProjectV2, type ProjectV2Field, type ProjectV2Item, type ProjectV2View, type ProjectWithViews, type ProjectsQueryResponse, type RepoInfo, type ResolvedSettings, SETTING_DISPLAY_NAMES, SYNCABLE_KEYS, type SettingConflict, type SettingsDiff, type SettingsSource, type SingleSelectFieldValue, type StatusField, type SyncableSettingKey, type SyncableSettings, type TextFieldValue, type TokenProvider, VSCODE_TO_CLI_MAP, branchExists, buildIssueUrl, buildOrgProjectUrl, buildProjectUrl, buildPullRequestUrl, buildRepoUrl, checkoutBranch, computeSettingsDiff, createBranch, detectRepository, fetchOrigin, formatConflict, generateBranchName, getAllBranches, getCommitsAhead, getCommitsBehind, getCurrentBranch, getDefaultBranch, getDiffSummary, getLocalBranches, getRemoteBranches, getRepositoryRoot, hasDifferences, hasUncommittedChanges, isGitRepository, normalizeVSCodeSettings, parseBranchLink, parseGitHubUrl, parseIssueUrl, pullLatest, queries, removeBranchLinkFromBody, resolveConflicts, sanitizeForBranchName, setBranchLinkInBody, skip, toVSCodeSettings, useCli, useCustom, useVSCode };
|
|
1056
|
+
export { type AssigneeInfo, type AuthError, BranchLinker, CLI_TO_VSCODE_MAP, type Collaborator, type ConflictChoices, type ConflictResolution, DEFAULT_VALUES, type DateFieldValue, type FieldInfo, type FieldValue, type FieldValueConnection, GitHubAPI, type GitHubAPIOptions, type GitOptions, type IssueDetails, type IssueReference, type IterationFieldValue, type LabelInfo, type NumberFieldValue, type Project, type ProjectConfig, type ProjectItem, type ProjectItemContent, type ProjectItemsQueryResponse, type ProjectV2, type ProjectV2Field, type ProjectV2Item, type ProjectV2View, type ProjectWithViews, type ProjectsQueryResponse, type RepoInfo, type ResolvedSettings, SETTING_DISPLAY_NAMES, SYNCABLE_KEYS, type SettingConflict, type SettingsDiff, type SettingsSource, type SingleSelectFieldValue, type StatusField, type SyncableSettingKey, type SyncableSettings, type TextFieldValue, type TokenProvider, VSCODE_TO_CLI_MAP, type WorktreeInfo, branchExists, buildIssueUrl, buildOrgProjectUrl, buildProjectUrl, buildPullRequestUrl, buildRepoUrl, checkoutBranch, computeSettingsDiff, createBranch, createWorktree, detectRepository, extractIssueNumberFromBranch, fetchOrigin, formatConflict, generateBranchName, generateWorktreePath, getAllBranches, getCommitsAhead, getCommitsBehind, getCurrentBranch, getDefaultBranch, getDiffSummary, getLocalBranches, getRemoteBranches, getRepositoryRoot, getWorktreeForBranch, hasDifferences, hasUncommittedChanges, isGitRepository, listWorktrees, normalizeVSCodeSettings, parseBranchLink, parseGitHubUrl, parseIssueUrl, pullLatest, queries, removeBranchLinkFromBody, removeWorktree, resolveConflicts, sanitizeForBranchName, setBranchLinkInBody, skip, toVSCodeSettings, useCli, useCustom, useVSCode, worktreeExists };
|
package/dist/index.js
CHANGED
|
@@ -339,7 +339,7 @@ var REMOVE_LABELS_MUTATION = `
|
|
|
339
339
|
var ISSUES_WITH_LABEL_QUERY = `
|
|
340
340
|
query($owner: String!, $name: String!, $labels: [String!]) {
|
|
341
341
|
repository(owner: $owner, name: $name) {
|
|
342
|
-
issues(first: 10, labels: $labels, states: [OPEN]) {
|
|
342
|
+
issues(first: 10, labels: $labels, states: [OPEN, CLOSED]) {
|
|
343
343
|
nodes {
|
|
344
344
|
number
|
|
345
345
|
}
|
|
@@ -1092,6 +1092,7 @@ var BranchLinker = class {
|
|
|
1092
1092
|
// src/git-utils.ts
|
|
1093
1093
|
import { exec } from "child_process";
|
|
1094
1094
|
import { promisify } from "util";
|
|
1095
|
+
import { homedir } from "os";
|
|
1095
1096
|
|
|
1096
1097
|
// src/url-parser.ts
|
|
1097
1098
|
function parseGitHubUrl(url) {
|
|
@@ -1144,6 +1145,28 @@ function buildOrgProjectUrl(org, projectNumber) {
|
|
|
1144
1145
|
}
|
|
1145
1146
|
|
|
1146
1147
|
// src/git-utils.ts
|
|
1148
|
+
function sanitizeForPath(input) {
|
|
1149
|
+
return String(input).replace(/\.\./g, "_").replace(/[;&|`$(){}[\]<>!]/g, "").replace(/\s+/g, "-").replace(/[^a-zA-Z0-9_\-./]/g, "_");
|
|
1150
|
+
}
|
|
1151
|
+
function validateBranchName(branch) {
|
|
1152
|
+
if (!branch || branch.trim().length === 0) {
|
|
1153
|
+
throw new Error("Branch name cannot be empty");
|
|
1154
|
+
}
|
|
1155
|
+
const dangerousChars = /[`$\\!;|&<>(){}[\]'"]/;
|
|
1156
|
+
if (dangerousChars.test(branch)) {
|
|
1157
|
+
throw new Error(`Branch name contains invalid characters: ${branch}`);
|
|
1158
|
+
}
|
|
1159
|
+
const gitInvalidChars = /[\s~^:?*\[\\]/;
|
|
1160
|
+
if (gitInvalidChars.test(branch)) {
|
|
1161
|
+
throw new Error(`Branch name contains invalid git characters: ${branch}`);
|
|
1162
|
+
}
|
|
1163
|
+
if (branch.includes("..")) {
|
|
1164
|
+
throw new Error(`Branch name cannot contain '..': ${branch}`);
|
|
1165
|
+
}
|
|
1166
|
+
if (/^[./]|[./]$/.test(branch)) {
|
|
1167
|
+
throw new Error(`Branch name cannot start or end with '/' or '.': ${branch}`);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1147
1170
|
var execAsync = promisify(exec);
|
|
1148
1171
|
async function execGit(command, options = {}) {
|
|
1149
1172
|
const cwd = options.cwd || process.cwd();
|
|
@@ -1245,6 +1268,25 @@ function generateBranchName(pattern, vars, maxLength = 60) {
|
|
|
1245
1268
|
}
|
|
1246
1269
|
return branch;
|
|
1247
1270
|
}
|
|
1271
|
+
function extractIssueNumberFromBranch(branchName) {
|
|
1272
|
+
const patterns = [
|
|
1273
|
+
/\/(\d+)-/,
|
|
1274
|
+
// user/123-title
|
|
1275
|
+
/^(\d+)-/,
|
|
1276
|
+
// 123-title
|
|
1277
|
+
/-(\d+)-/,
|
|
1278
|
+
// feature-123-title
|
|
1279
|
+
/[/#](\d+)$/
|
|
1280
|
+
// ends with #123 or /123
|
|
1281
|
+
];
|
|
1282
|
+
for (const pattern of patterns) {
|
|
1283
|
+
const match = branchName.match(pattern);
|
|
1284
|
+
if (match) {
|
|
1285
|
+
return parseInt(match[1], 10);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
return null;
|
|
1289
|
+
}
|
|
1248
1290
|
async function getLocalBranches(options = {}) {
|
|
1249
1291
|
try {
|
|
1250
1292
|
const { stdout } = await execGit('git branch --format="%(refname:short)"', options);
|
|
@@ -1291,6 +1333,90 @@ async function getDefaultBranch(options = {}) {
|
|
|
1291
1333
|
}
|
|
1292
1334
|
return "master";
|
|
1293
1335
|
}
|
|
1336
|
+
function validatePath(path) {
|
|
1337
|
+
if (!path || path.trim().length === 0) {
|
|
1338
|
+
throw new Error("Path cannot be empty");
|
|
1339
|
+
}
|
|
1340
|
+
const dangerousChars = /[`$;|&<>(){}[\]'"\n\r]/;
|
|
1341
|
+
if (dangerousChars.test(path)) {
|
|
1342
|
+
throw new Error(`Path contains invalid characters: ${path}`);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
async function createWorktree(worktreePath, branch, options = {}) {
|
|
1346
|
+
validateBranchName(branch);
|
|
1347
|
+
validatePath(worktreePath);
|
|
1348
|
+
const localExists = await branchExists(branch, options);
|
|
1349
|
+
if (localExists) {
|
|
1350
|
+
await execGit(`git worktree add "${worktreePath}" "${branch}"`, options);
|
|
1351
|
+
} else {
|
|
1352
|
+
try {
|
|
1353
|
+
await execGit(`git worktree add "${worktreePath}" -b "${branch}" "origin/${branch}"`, options);
|
|
1354
|
+
} catch {
|
|
1355
|
+
await execGit(`git worktree add -b "${branch}" "${worktreePath}"`, options);
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
async function removeWorktree(worktreePath, options = {}, force = false) {
|
|
1360
|
+
validatePath(worktreePath);
|
|
1361
|
+
const forceFlag = force ? "--force" : "";
|
|
1362
|
+
await execGit(`git worktree remove ${forceFlag} "${worktreePath}"`, options);
|
|
1363
|
+
}
|
|
1364
|
+
async function listWorktrees(options = {}) {
|
|
1365
|
+
try {
|
|
1366
|
+
const { stdout } = await execGit("git worktree list --porcelain", options);
|
|
1367
|
+
const worktrees = [];
|
|
1368
|
+
const entries = stdout.trim().split("\n\n");
|
|
1369
|
+
for (const entry of entries) {
|
|
1370
|
+
if (!entry.trim()) continue;
|
|
1371
|
+
const lines = entry.split("\n");
|
|
1372
|
+
const info = {
|
|
1373
|
+
isMain: false,
|
|
1374
|
+
branch: null
|
|
1375
|
+
};
|
|
1376
|
+
for (const line of lines) {
|
|
1377
|
+
if (line.startsWith("worktree ")) {
|
|
1378
|
+
info.path = line.substring(9);
|
|
1379
|
+
} else if (line.startsWith("HEAD ")) {
|
|
1380
|
+
info.head = line.substring(5);
|
|
1381
|
+
} else if (line.startsWith("branch ")) {
|
|
1382
|
+
info.branch = line.substring(7).replace(/^refs\/heads\//, "");
|
|
1383
|
+
} else if (line === "bare") {
|
|
1384
|
+
info.isMain = true;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
if (worktrees.length === 0) {
|
|
1388
|
+
info.isMain = true;
|
|
1389
|
+
}
|
|
1390
|
+
if (info.path && info.head) {
|
|
1391
|
+
worktrees.push(info);
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
return worktrees;
|
|
1395
|
+
} catch {
|
|
1396
|
+
return [];
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
async function getWorktreeForBranch(branch, options = {}) {
|
|
1400
|
+
const worktrees = await listWorktrees(options);
|
|
1401
|
+
return worktrees.find((wt) => wt.branch === branch) || null;
|
|
1402
|
+
}
|
|
1403
|
+
async function worktreeExists(worktreePath, options = {}) {
|
|
1404
|
+
const worktrees = await listWorktrees(options);
|
|
1405
|
+
return worktrees.some((wt) => wt.path === worktreePath);
|
|
1406
|
+
}
|
|
1407
|
+
function generateWorktreePath(basePath, repoName, identifier, title) {
|
|
1408
|
+
const safeRepoName = sanitizeForPath(repoName);
|
|
1409
|
+
let dirName;
|
|
1410
|
+
if (title && typeof identifier === "number") {
|
|
1411
|
+
const titleSlug = sanitizeForBranchName(title).substring(0, 35).replace(/-$/, "");
|
|
1412
|
+
dirName = `${identifier}-${titleSlug}`;
|
|
1413
|
+
} else {
|
|
1414
|
+
dirName = sanitizeForPath(String(identifier));
|
|
1415
|
+
}
|
|
1416
|
+
const expandedBase = basePath.startsWith("~") ? basePath.replace("~", homedir()) : basePath;
|
|
1417
|
+
const cleanBase = expandedBase.replace(/\/+$/, "");
|
|
1418
|
+
return `${cleanBase}/${safeRepoName}/${dirName}`;
|
|
1419
|
+
}
|
|
1294
1420
|
|
|
1295
1421
|
// src/sync.ts
|
|
1296
1422
|
var SYNCABLE_KEYS = [
|
|
@@ -1470,10 +1596,13 @@ export {
|
|
|
1470
1596
|
checkoutBranch,
|
|
1471
1597
|
computeSettingsDiff,
|
|
1472
1598
|
createBranch,
|
|
1599
|
+
createWorktree,
|
|
1473
1600
|
detectRepository,
|
|
1601
|
+
extractIssueNumberFromBranch,
|
|
1474
1602
|
fetchOrigin,
|
|
1475
1603
|
formatConflict,
|
|
1476
1604
|
generateBranchName,
|
|
1605
|
+
generateWorktreePath,
|
|
1477
1606
|
getAllBranches,
|
|
1478
1607
|
getCommitsAhead,
|
|
1479
1608
|
getCommitsBehind,
|
|
@@ -1483,9 +1612,11 @@ export {
|
|
|
1483
1612
|
getLocalBranches,
|
|
1484
1613
|
getRemoteBranches,
|
|
1485
1614
|
getRepositoryRoot,
|
|
1615
|
+
getWorktreeForBranch,
|
|
1486
1616
|
hasDifferences,
|
|
1487
1617
|
hasUncommittedChanges,
|
|
1488
1618
|
isGitRepository,
|
|
1619
|
+
listWorktrees,
|
|
1489
1620
|
normalizeVSCodeSettings,
|
|
1490
1621
|
parseBranchLink,
|
|
1491
1622
|
parseGitHubUrl,
|
|
@@ -1493,6 +1624,7 @@ export {
|
|
|
1493
1624
|
pullLatest,
|
|
1494
1625
|
queries_exports as queries,
|
|
1495
1626
|
removeBranchLinkFromBody,
|
|
1627
|
+
removeWorktree,
|
|
1496
1628
|
resolveConflicts,
|
|
1497
1629
|
sanitizeForBranchName,
|
|
1498
1630
|
setBranchLinkInBody,
|
|
@@ -1500,5 +1632,6 @@ export {
|
|
|
1500
1632
|
toVSCodeSettings,
|
|
1501
1633
|
useCli,
|
|
1502
1634
|
useCustom,
|
|
1503
|
-
useVSCode
|
|
1635
|
+
useVSCode,
|
|
1636
|
+
worktreeExists
|
|
1504
1637
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bretwardjames/ghp-core",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.2",
|
|
4
4
|
"description": "Shared core library for GitHub Projects tools",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
21
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
19
25
|
"keywords": [
|
|
20
26
|
"github",
|
|
21
27
|
"projects",
|
|
@@ -38,10 +44,5 @@
|
|
|
38
44
|
"@types/node": "^20.10.0",
|
|
39
45
|
"tsup": "^8.0.0",
|
|
40
46
|
"typescript": "^5.3.2"
|
|
41
|
-
},
|
|
42
|
-
"scripts": {
|
|
43
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
44
|
-
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
45
|
-
"typecheck": "tsc --noEmit"
|
|
46
47
|
}
|
|
47
|
-
}
|
|
48
|
+
}
|