sync-worktrees 1.7.3 → 1.7.5
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/constants.d.ts +54 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +66 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors/index.d.ts +51 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +119 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/services/git.service.d.ts.map +1 -1
- package/dist/services/git.service.js +86 -40
- package/dist/services/git.service.js.map +1 -1
- package/dist/services/path-resolution.service.d.ts +7 -0
- package/dist/services/path-resolution.service.d.ts.map +1 -0
- package/dist/services/path-resolution.service.js +58 -0
- package/dist/services/path-resolution.service.js.map +1 -0
- package/dist/services/worktree-metadata.service.d.ts +12 -0
- package/dist/services/worktree-metadata.service.d.ts.map +1 -1
- package/dist/services/worktree-metadata.service.js +162 -3
- package/dist/services/worktree-metadata.service.js.map +1 -1
- package/dist/services/worktree-status.service.d.ts +28 -0
- package/dist/services/worktree-status.service.d.ts.map +1 -0
- package/dist/services/worktree-status.service.js +229 -0
- package/dist/services/worktree-status.service.js.map +1 -0
- package/dist/services/worktree-sync.service.d.ts.map +1 -1
- package/dist/services/worktree-sync.service.js +7 -10
- package/dist/services/worktree-sync.service.js.map +1 -1
- package/dist/utils/lfs-error.d.ts +6 -0
- package/dist/utils/lfs-error.d.ts.map +1 -1
- package/dist/utils/lfs-error.js +16 -14
- package/dist/utils/lfs-error.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export declare const GIT_CONSTANTS: {
|
|
2
|
+
readonly REMOTE_PREFIX: "origin/";
|
|
3
|
+
readonly REMOTE_NAME: "origin";
|
|
4
|
+
readonly HEAD_REF: "/HEAD";
|
|
5
|
+
readonly DEFAULT_BRANCH: "main";
|
|
6
|
+
readonly BARE_DIR_NAME: ".bare";
|
|
7
|
+
readonly DIVERGED_DIR_NAME: ".diverged";
|
|
8
|
+
readonly REFS: {
|
|
9
|
+
readonly HEADS: "refs/heads/";
|
|
10
|
+
readonly REMOTES: "refs/remotes/origin";
|
|
11
|
+
readonly REMOTES_ORIGIN: "refs/remotes/origin/*";
|
|
12
|
+
};
|
|
13
|
+
readonly FETCH_CONFIG: "+refs/heads/*:refs/remotes/origin/*";
|
|
14
|
+
};
|
|
15
|
+
export declare const GIT_OPERATIONS: {
|
|
16
|
+
readonly MERGE_HEAD: "MERGE_HEAD";
|
|
17
|
+
readonly CHERRY_PICK_HEAD: "CHERRY_PICK_HEAD";
|
|
18
|
+
readonly REVERT_HEAD: "REVERT_HEAD";
|
|
19
|
+
readonly BISECT_LOG: "BISECT_LOG";
|
|
20
|
+
readonly REBASE_MERGE: "rebase-merge";
|
|
21
|
+
readonly REBASE_APPLY: "rebase-apply";
|
|
22
|
+
};
|
|
23
|
+
export declare const DEFAULT_CONFIG: {
|
|
24
|
+
readonly CRON_SCHEDULE: "0 * * * *";
|
|
25
|
+
readonly RETRY: {
|
|
26
|
+
readonly MAX_ATTEMPTS: 3;
|
|
27
|
+
readonly MAX_LFS_RETRIES: 2;
|
|
28
|
+
readonly INITIAL_DELAY_MS: 1000;
|
|
29
|
+
readonly MAX_DELAY_MS: 30000;
|
|
30
|
+
readonly BACKOFF_MULTIPLIER: 2;
|
|
31
|
+
};
|
|
32
|
+
readonly UPDATE_EXISTING_WORKTREES: true;
|
|
33
|
+
};
|
|
34
|
+
export declare const ERROR_MESSAGES: {
|
|
35
|
+
readonly GIT_NOT_INITIALIZED: "Git service not initialized. Call initialize() first.";
|
|
36
|
+
readonly ALREADY_EXISTS: "already exists";
|
|
37
|
+
readonly ALREADY_REGISTERED: "already registered worktree";
|
|
38
|
+
readonly FAST_FORWARD_FAILED: readonly ["Not possible to fast-forward", "fatal: Not possible to fast-forward, aborting", "cannot fast-forward"];
|
|
39
|
+
readonly NO_UPSTREAM: readonly ["fatal: no upstream configured", "no upstream configured for branch", "fatal: ambiguous argument", "unknown revision or path"];
|
|
40
|
+
readonly LFS_ERROR: readonly ["smudge filter lfs failed", "git-lfs", "LFS"];
|
|
41
|
+
readonly EXDEV: "EXDEV";
|
|
42
|
+
};
|
|
43
|
+
export declare const TEST_TIMEOUT: {
|
|
44
|
+
readonly DEFAULT: 10000;
|
|
45
|
+
readonly E2E: 60000;
|
|
46
|
+
};
|
|
47
|
+
export declare const PATH_CONSTANTS: {
|
|
48
|
+
readonly GIT_DIR: ".git";
|
|
49
|
+
readonly README: "README";
|
|
50
|
+
};
|
|
51
|
+
export declare const METADATA_CONSTANTS: {
|
|
52
|
+
readonly MAX_HISTORY_ENTRIES: 10;
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;;;;;;;;;;;;;CAahB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;CAOjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;;;CAUjB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;CAiBjB,CAAC;AAEX,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,eAAO,MAAM,cAAc;;;CAGjB,CAAC;AAEX,eAAO,MAAM,kBAAkB;;CAErB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.METADATA_CONSTANTS = exports.PATH_CONSTANTS = exports.TEST_TIMEOUT = exports.ERROR_MESSAGES = exports.DEFAULT_CONFIG = exports.GIT_OPERATIONS = exports.GIT_CONSTANTS = void 0;
|
|
4
|
+
exports.GIT_CONSTANTS = {
|
|
5
|
+
REMOTE_PREFIX: "origin/",
|
|
6
|
+
REMOTE_NAME: "origin",
|
|
7
|
+
HEAD_REF: "/HEAD",
|
|
8
|
+
DEFAULT_BRANCH: "main",
|
|
9
|
+
BARE_DIR_NAME: ".bare",
|
|
10
|
+
DIVERGED_DIR_NAME: ".diverged",
|
|
11
|
+
REFS: {
|
|
12
|
+
HEADS: "refs/heads/",
|
|
13
|
+
REMOTES: "refs/remotes/origin",
|
|
14
|
+
REMOTES_ORIGIN: "refs/remotes/origin/*",
|
|
15
|
+
},
|
|
16
|
+
FETCH_CONFIG: "+refs/heads/*:refs/remotes/origin/*",
|
|
17
|
+
};
|
|
18
|
+
exports.GIT_OPERATIONS = {
|
|
19
|
+
MERGE_HEAD: "MERGE_HEAD",
|
|
20
|
+
CHERRY_PICK_HEAD: "CHERRY_PICK_HEAD",
|
|
21
|
+
REVERT_HEAD: "REVERT_HEAD",
|
|
22
|
+
BISECT_LOG: "BISECT_LOG",
|
|
23
|
+
REBASE_MERGE: "rebase-merge",
|
|
24
|
+
REBASE_APPLY: "rebase-apply",
|
|
25
|
+
};
|
|
26
|
+
exports.DEFAULT_CONFIG = {
|
|
27
|
+
CRON_SCHEDULE: "0 * * * *",
|
|
28
|
+
RETRY: {
|
|
29
|
+
MAX_ATTEMPTS: 3,
|
|
30
|
+
MAX_LFS_RETRIES: 2,
|
|
31
|
+
INITIAL_DELAY_MS: 1000,
|
|
32
|
+
MAX_DELAY_MS: 30000,
|
|
33
|
+
BACKOFF_MULTIPLIER: 2,
|
|
34
|
+
},
|
|
35
|
+
UPDATE_EXISTING_WORKTREES: true,
|
|
36
|
+
};
|
|
37
|
+
exports.ERROR_MESSAGES = {
|
|
38
|
+
GIT_NOT_INITIALIZED: "Git service not initialized. Call initialize() first.",
|
|
39
|
+
ALREADY_EXISTS: "already exists",
|
|
40
|
+
ALREADY_REGISTERED: "already registered worktree",
|
|
41
|
+
FAST_FORWARD_FAILED: [
|
|
42
|
+
"Not possible to fast-forward",
|
|
43
|
+
"fatal: Not possible to fast-forward, aborting",
|
|
44
|
+
"cannot fast-forward",
|
|
45
|
+
],
|
|
46
|
+
NO_UPSTREAM: [
|
|
47
|
+
"fatal: no upstream configured",
|
|
48
|
+
"no upstream configured for branch",
|
|
49
|
+
"fatal: ambiguous argument",
|
|
50
|
+
"unknown revision or path",
|
|
51
|
+
],
|
|
52
|
+
LFS_ERROR: ["smudge filter lfs failed", "git-lfs", "LFS"],
|
|
53
|
+
EXDEV: "EXDEV",
|
|
54
|
+
};
|
|
55
|
+
exports.TEST_TIMEOUT = {
|
|
56
|
+
DEFAULT: 10000,
|
|
57
|
+
E2E: 60000,
|
|
58
|
+
};
|
|
59
|
+
exports.PATH_CONSTANTS = {
|
|
60
|
+
GIT_DIR: ".git",
|
|
61
|
+
README: "README",
|
|
62
|
+
};
|
|
63
|
+
exports.METADATA_CONSTANTS = {
|
|
64
|
+
MAX_HISTORY_ENTRIES: 10,
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,aAAa,GAAG;IAC3B,aAAa,EAAE,SAAS;IACxB,WAAW,EAAE,QAAQ;IACrB,QAAQ,EAAE,OAAO;IACjB,cAAc,EAAE,MAAM;IACtB,aAAa,EAAE,OAAO;IACtB,iBAAiB,EAAE,WAAW;IAC9B,IAAI,EAAE;QACJ,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,qBAAqB;QAC9B,cAAc,EAAE,uBAAuB;KACxC;IACD,YAAY,EAAE,qCAAqC;CAC3C,CAAC;AAEE,QAAA,cAAc,GAAG;IAC5B,UAAU,EAAE,YAAY;IACxB,gBAAgB,EAAE,kBAAkB;IACpC,WAAW,EAAE,aAAa;IAC1B,UAAU,EAAE,YAAY;IACxB,YAAY,EAAE,cAAc;IAC5B,YAAY,EAAE,cAAc;CACpB,CAAC;AAEE,QAAA,cAAc,GAAG;IAC5B,aAAa,EAAE,WAAW;IAC1B,KAAK,EAAE;QACL,YAAY,EAAE,CAAC;QACf,eAAe,EAAE,CAAC;QAClB,gBAAgB,EAAE,IAAI;QACtB,YAAY,EAAE,KAAK;QACnB,kBAAkB,EAAE,CAAC;KACtB;IACD,yBAAyB,EAAE,IAAI;CACvB,CAAC;AAEE,QAAA,cAAc,GAAG;IAC5B,mBAAmB,EAAE,uDAAuD;IAC5E,cAAc,EAAE,gBAAgB;IAChC,kBAAkB,EAAE,6BAA6B;IACjD,mBAAmB,EAAE;QACnB,8BAA8B;QAC9B,+CAA+C;QAC/C,qBAAqB;KACtB;IACD,WAAW,EAAE;QACX,+BAA+B;QAC/B,mCAAmC;QACnC,2BAA2B;QAC3B,0BAA0B;KAC3B;IACD,SAAS,EAAE,CAAC,0BAA0B,EAAE,SAAS,EAAE,KAAK,CAAC;IACzD,KAAK,EAAE,OAAO;CACN,CAAC;AAEE,QAAA,YAAY,GAAG;IAC1B,OAAO,EAAE,KAAK;IACd,GAAG,EAAE,KAAK;CACF,CAAC;AAEE,QAAA,cAAc,GAAG;IAC5B,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,QAAQ;CACR,CAAC;AAEE,QAAA,kBAAkB,GAAG;IAChC,mBAAmB,EAAE,EAAE;CACf,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export declare class SyncWorktreesError extends Error {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly cause?: Error | undefined;
|
|
4
|
+
constructor(message: string, code: string, cause?: Error | undefined);
|
|
5
|
+
}
|
|
6
|
+
export declare class GitError extends SyncWorktreesError {
|
|
7
|
+
constructor(message: string, code: string, cause?: Error);
|
|
8
|
+
}
|
|
9
|
+
export declare class GitNotInitializedError extends GitError {
|
|
10
|
+
constructor();
|
|
11
|
+
}
|
|
12
|
+
export declare class GitOperationError extends GitError {
|
|
13
|
+
constructor(operation: string, details: string, cause?: Error);
|
|
14
|
+
}
|
|
15
|
+
export declare class FastForwardError extends GitError {
|
|
16
|
+
readonly branchName: string;
|
|
17
|
+
constructor(branchName: string, cause?: Error);
|
|
18
|
+
}
|
|
19
|
+
export declare class WorktreeError extends SyncWorktreesError {
|
|
20
|
+
constructor(message: string, code: string, cause?: Error);
|
|
21
|
+
}
|
|
22
|
+
export declare class WorktreeAlreadyExistsError extends WorktreeError {
|
|
23
|
+
readonly path: string;
|
|
24
|
+
readonly branchName: string;
|
|
25
|
+
constructor(path: string, branchName: string);
|
|
26
|
+
}
|
|
27
|
+
export declare class WorktreeNotCleanError extends WorktreeError {
|
|
28
|
+
readonly path: string;
|
|
29
|
+
readonly reasons: string[];
|
|
30
|
+
constructor(path: string, reasons: string[]);
|
|
31
|
+
}
|
|
32
|
+
export declare class ConfigError extends SyncWorktreesError {
|
|
33
|
+
constructor(message: string, code: string, cause?: Error);
|
|
34
|
+
}
|
|
35
|
+
export declare class ConfigValidationError extends ConfigError {
|
|
36
|
+
readonly field: string;
|
|
37
|
+
readonly reason: string;
|
|
38
|
+
constructor(field: string, reason: string);
|
|
39
|
+
}
|
|
40
|
+
export declare class PathResolutionError extends SyncWorktreesError {
|
|
41
|
+
readonly path: string;
|
|
42
|
+
readonly reason: string;
|
|
43
|
+
constructor(path: string, reason: string);
|
|
44
|
+
}
|
|
45
|
+
export declare class LfsError extends GitError {
|
|
46
|
+
constructor(message: string, cause?: Error);
|
|
47
|
+
}
|
|
48
|
+
export declare function isLfsError(error: Error | string): boolean;
|
|
49
|
+
export declare function isFastForwardError(error: Error | string): boolean;
|
|
50
|
+
export declare function isNoUpstreamError(error: Error | string): boolean;
|
|
51
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAEA,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,IAAI,EAAE,MAAM;aACZ,KAAK,CAAC,EAAE,KAAK;gBAF7B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,KAAK,YAAA;CAShC;AAED,qBAAa,QAAS,SAAQ,kBAAkB;gBAClC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,sBAAuB,SAAQ,QAAQ;;CAInD;AAED,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG9D;AAED,qBAAa,gBAAiB,SAAQ,QAAQ;aAE1B,UAAU,EAAE,MAAM;gBAAlB,UAAU,EAAE,MAAM,EAClC,KAAK,CAAC,EAAE,KAAK;CAIhB;AAED,qBAAa,aAAc,SAAQ,kBAAkB;gBACvC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,0BAA2B,SAAQ,aAAa;aAEzC,IAAI,EAAE,MAAM;aACZ,UAAU,EAAE,MAAM;gBADlB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM;CAIrC;AAED,qBAAa,qBAAsB,SAAQ,aAAa;aAEpC,IAAI,EAAE,MAAM;aACZ,OAAO,EAAE,MAAM,EAAE;gBADjB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EAAE;CAIpC;AAED,qBAAa,WAAY,SAAQ,kBAAkB;gBACrC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAGzD;AAED,qBAAa,qBAAsB,SAAQ,WAAW;aAElC,KAAK,EAAE,MAAM;aACb,MAAM,EAAE,MAAM;gBADd,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM;CAIjC;AAED,qBAAa,mBAAoB,SAAQ,kBAAkB;aAEvC,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM;gBADd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM;CAIjC;AAED,qBAAa,QAAS,SAAQ,QAAQ;gBACxB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAG3C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAGzD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAGjE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAGhE"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LfsError = exports.PathResolutionError = exports.ConfigValidationError = exports.ConfigError = exports.WorktreeNotCleanError = exports.WorktreeAlreadyExistsError = exports.WorktreeError = exports.FastForwardError = exports.GitOperationError = exports.GitNotInitializedError = exports.GitError = exports.SyncWorktreesError = void 0;
|
|
4
|
+
exports.isLfsError = isLfsError;
|
|
5
|
+
exports.isFastForwardError = isFastForwardError;
|
|
6
|
+
exports.isNoUpstreamError = isNoUpstreamError;
|
|
7
|
+
const constants_1 = require("../constants");
|
|
8
|
+
class SyncWorktreesError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
cause;
|
|
11
|
+
constructor(message, code, cause) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.cause = cause;
|
|
15
|
+
this.name = this.constructor.name;
|
|
16
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
17
|
+
if (cause && cause.stack) {
|
|
18
|
+
this.stack = `${this.stack}\nCaused by: ${cause.stack}`;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.SyncWorktreesError = SyncWorktreesError;
|
|
23
|
+
class GitError extends SyncWorktreesError {
|
|
24
|
+
constructor(message, code, cause) {
|
|
25
|
+
super(message, `GIT_${code}`, cause);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.GitError = GitError;
|
|
29
|
+
class GitNotInitializedError extends GitError {
|
|
30
|
+
constructor() {
|
|
31
|
+
super(constants_1.ERROR_MESSAGES.GIT_NOT_INITIALIZED, "NOT_INITIALIZED");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.GitNotInitializedError = GitNotInitializedError;
|
|
35
|
+
class GitOperationError extends GitError {
|
|
36
|
+
constructor(operation, details, cause) {
|
|
37
|
+
super(`Git operation '${operation}' failed: ${details}`, "OPERATION_FAILED", cause);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.GitOperationError = GitOperationError;
|
|
41
|
+
class FastForwardError extends GitError {
|
|
42
|
+
branchName;
|
|
43
|
+
constructor(branchName, cause) {
|
|
44
|
+
super(`Cannot fast-forward branch '${branchName}'`, "FAST_FORWARD_FAILED", cause);
|
|
45
|
+
this.branchName = branchName;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.FastForwardError = FastForwardError;
|
|
49
|
+
class WorktreeError extends SyncWorktreesError {
|
|
50
|
+
constructor(message, code, cause) {
|
|
51
|
+
super(message, `WORKTREE_${code}`, cause);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.WorktreeError = WorktreeError;
|
|
55
|
+
class WorktreeAlreadyExistsError extends WorktreeError {
|
|
56
|
+
path;
|
|
57
|
+
branchName;
|
|
58
|
+
constructor(path, branchName) {
|
|
59
|
+
super(`Worktree already exists at '${path}' for branch '${branchName}'`, "ALREADY_EXISTS");
|
|
60
|
+
this.path = path;
|
|
61
|
+
this.branchName = branchName;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.WorktreeAlreadyExistsError = WorktreeAlreadyExistsError;
|
|
65
|
+
class WorktreeNotCleanError extends WorktreeError {
|
|
66
|
+
path;
|
|
67
|
+
reasons;
|
|
68
|
+
constructor(path, reasons) {
|
|
69
|
+
super(`Worktree at '${path}' is not clean: ${reasons.join(", ")}`, "NOT_CLEAN");
|
|
70
|
+
this.path = path;
|
|
71
|
+
this.reasons = reasons;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.WorktreeNotCleanError = WorktreeNotCleanError;
|
|
75
|
+
class ConfigError extends SyncWorktreesError {
|
|
76
|
+
constructor(message, code, cause) {
|
|
77
|
+
super(message, `CONFIG_${code}`, cause);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.ConfigError = ConfigError;
|
|
81
|
+
class ConfigValidationError extends ConfigError {
|
|
82
|
+
field;
|
|
83
|
+
reason;
|
|
84
|
+
constructor(field, reason) {
|
|
85
|
+
super(`Invalid configuration for '${field}': ${reason}`, "VALIDATION_FAILED");
|
|
86
|
+
this.field = field;
|
|
87
|
+
this.reason = reason;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
exports.ConfigValidationError = ConfigValidationError;
|
|
91
|
+
class PathResolutionError extends SyncWorktreesError {
|
|
92
|
+
path;
|
|
93
|
+
reason;
|
|
94
|
+
constructor(path, reason) {
|
|
95
|
+
super(`Path resolution failed for '${path}': ${reason}`, "PATH_RESOLUTION_FAILED");
|
|
96
|
+
this.path = path;
|
|
97
|
+
this.reason = reason;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.PathResolutionError = PathResolutionError;
|
|
101
|
+
class LfsError extends GitError {
|
|
102
|
+
constructor(message, cause) {
|
|
103
|
+
super(`LFS operation failed: ${message}`, "LFS_ERROR", cause);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.LfsError = LfsError;
|
|
107
|
+
function isLfsError(error) {
|
|
108
|
+
const message = typeof error === "string" ? error : error.message;
|
|
109
|
+
return constants_1.ERROR_MESSAGES.LFS_ERROR.some((pattern) => message.includes(pattern));
|
|
110
|
+
}
|
|
111
|
+
function isFastForwardError(error) {
|
|
112
|
+
const message = typeof error === "string" ? error : error.message;
|
|
113
|
+
return constants_1.ERROR_MESSAGES.FAST_FORWARD_FAILED.some((pattern) => message.includes(pattern));
|
|
114
|
+
}
|
|
115
|
+
function isNoUpstreamError(error) {
|
|
116
|
+
const message = typeof error === "string" ? error : error.message;
|
|
117
|
+
return constants_1.ERROR_MESSAGES.NO_UPSTREAM.some((pattern) => message.includes(pattern));
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.service.d.ts","sourceRoot":"","sources":["../../src/services/git.service.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"git.service.d.ts","sourceRoot":"","sources":["../../src/services/git.service.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,qBAAa,UAAU;IAOT,OAAO,CAAC,MAAM;IAN1B,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,eAAe,CAA0B;gBAE7B,MAAM,EAAE,MAAM;IAM5B,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC;IA6HtC,MAAM,IAAI,SAAS;IAOnB,gBAAgB,IAAI,MAAM;IAIpB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAWzB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9C,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAStC,6BAA6B,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,IAAI,CAAA;KAAE,EAAE,CAAC;YAkC1E,sBAAsB;IAsB9B,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8HpE,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcnD,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAM/B,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YAMnD,cAAc;IAStB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyC1D,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkEvD,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYzD,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW7D,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA+B9D,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;YAM3B,mBAAmB;IAsCjC,OAAO,CAAC,gBAAgB;IAIlB,YAAY,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAK3D,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBxD,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCnD,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBlF,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBtE,kBAAkB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAe1E,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBpE,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAMvD,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAOrC,oBAAoB;CAiCnC"}
|
|
@@ -41,6 +41,7 @@ const fs = __importStar(require("fs/promises"));
|
|
|
41
41
|
const path = __importStar(require("path"));
|
|
42
42
|
const simple_git_1 = __importDefault(require("simple-git"));
|
|
43
43
|
const git_url_1 = require("../utils/git-url");
|
|
44
|
+
const lfs_error_1 = require("../utils/lfs-error");
|
|
44
45
|
const worktree_metadata_service_1 = require("./worktree-metadata.service");
|
|
45
46
|
class GitService {
|
|
46
47
|
config;
|
|
@@ -132,7 +133,7 @@ class GitService {
|
|
|
132
133
|
}
|
|
133
134
|
}
|
|
134
135
|
catch (error) {
|
|
135
|
-
const errorMessage =
|
|
136
|
+
const errorMessage = (0, lfs_error_1.getErrorMessage)(error);
|
|
136
137
|
// Check if error is because directory already exists
|
|
137
138
|
if (errorMessage.includes("already exists")) {
|
|
138
139
|
console.log(`${this.defaultBranch} worktree directory already exists at '${absoluteWorktreePath}', skipping creation.`);
|
|
@@ -144,7 +145,7 @@ class GitService {
|
|
|
144
145
|
await bareGit.raw(["worktree", "add", absoluteWorktreePath, this.defaultBranch]);
|
|
145
146
|
}
|
|
146
147
|
catch (fallbackError) {
|
|
147
|
-
const fallbackErrorMessage =
|
|
148
|
+
const fallbackErrorMessage = (0, lfs_error_1.getErrorMessage)(fallbackError);
|
|
148
149
|
if (fallbackErrorMessage.includes("already exists")) {
|
|
149
150
|
console.log(`${this.defaultBranch} worktree directory already exists at '${absoluteWorktreePath}', skipping creation.`);
|
|
150
151
|
}
|
|
@@ -202,7 +203,8 @@ class GitService {
|
|
|
202
203
|
const branches = await git.branch(["-r"]);
|
|
203
204
|
return branches.all
|
|
204
205
|
.filter((b) => b.startsWith("origin/") && !b.endsWith("/HEAD"))
|
|
205
|
-
.map((b) => b.replace("origin/", ""))
|
|
206
|
+
.map((b) => b.replace("origin/", ""))
|
|
207
|
+
.filter((b) => b !== "origin" && b.length > 0);
|
|
206
208
|
}
|
|
207
209
|
async getRemoteBranchesWithActivity() {
|
|
208
210
|
const git = this.getGit();
|
|
@@ -221,6 +223,10 @@ class GitService {
|
|
|
221
223
|
const [ref, dateStr] = line.split("|", 2);
|
|
222
224
|
if (ref && dateStr && !ref.endsWith("/HEAD")) {
|
|
223
225
|
const branch = ref.replace("origin/", "");
|
|
226
|
+
// Skip invalid branch names
|
|
227
|
+
if (branch === "origin" || branch.length === 0) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
224
230
|
const lastActivity = new Date(dateStr);
|
|
225
231
|
// Skip if the date is invalid
|
|
226
232
|
if (!isNaN(lastActivity.getTime())) {
|
|
@@ -237,10 +243,11 @@ class GitService {
|
|
|
237
243
|
: (0, simple_git_1.default)(worktreePath);
|
|
238
244
|
const currentCommit = await worktreeGit.revparse(["HEAD"]);
|
|
239
245
|
const parentCommit = await bareGit.revparse([this.defaultBranch]);
|
|
240
|
-
await this.metadataService.
|
|
246
|
+
await this.metadataService.createInitialMetadataFromPath(this.bareRepoPath, worktreePath, currentCommit.trim(), `origin/${branchName}`, this.defaultBranch, parentCommit.trim());
|
|
241
247
|
}
|
|
242
248
|
catch (metadataError) {
|
|
243
|
-
console.
|
|
249
|
+
console.error(` - ❌ Failed to create metadata for '${branchName}': ${metadataError}`);
|
|
250
|
+
throw new Error(`Metadata creation failed for ${branchName}. This worktree cannot be auto-managed.`);
|
|
244
251
|
}
|
|
245
252
|
}
|
|
246
253
|
async addWorktree(branchName, worktreePath) {
|
|
@@ -298,6 +305,42 @@ class GitService {
|
|
|
298
305
|
await this.createWorktreeMetadata(bareGit, absoluteWorktreePath, branchName);
|
|
299
306
|
}
|
|
300
307
|
catch (error) {
|
|
308
|
+
const errorMessage = (0, lfs_error_1.getErrorMessage)(error);
|
|
309
|
+
// Re-throw metadata creation errors - these are fatal and should not fall back
|
|
310
|
+
if (errorMessage.includes("Metadata creation failed")) {
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
// Check if this is an "already registered" error
|
|
314
|
+
if (errorMessage.includes("already registered worktree")) {
|
|
315
|
+
console.warn(` - Worktree already registered but missing. Pruning and retrying...`);
|
|
316
|
+
await bareGit.raw(["worktree", "prune"]);
|
|
317
|
+
// Clean up directory if it exists
|
|
318
|
+
try {
|
|
319
|
+
await fs.rm(absoluteWorktreePath, { recursive: true, force: true });
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
// Directory might not exist, ignore
|
|
323
|
+
}
|
|
324
|
+
// Retry once after pruning
|
|
325
|
+
try {
|
|
326
|
+
await bareGit.raw([
|
|
327
|
+
"worktree",
|
|
328
|
+
"add",
|
|
329
|
+
"--track",
|
|
330
|
+
"-b",
|
|
331
|
+
branchName,
|
|
332
|
+
absoluteWorktreePath,
|
|
333
|
+
`origin/${branchName}`,
|
|
334
|
+
]);
|
|
335
|
+
console.log(` - Created worktree for '${branchName}' after pruning`);
|
|
336
|
+
await this.createWorktreeMetadata(bareGit, absoluteWorktreePath, branchName);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
catch (retryError) {
|
|
340
|
+
console.error(` - Failed to create worktree after pruning: ${retryError}`);
|
|
341
|
+
throw retryError;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
301
344
|
// If the worktree add fails with tracking, fall back to non-tracking version
|
|
302
345
|
// This handles edge cases where the remote branch might not exist yet
|
|
303
346
|
console.warn(` - Failed to create worktree with tracking, falling back to simple add: ${error}`);
|
|
@@ -328,27 +371,14 @@ class GitService {
|
|
|
328
371
|
}
|
|
329
372
|
async removeWorktree(worktreePath) {
|
|
330
373
|
const bareGit = (0, simple_git_1.default)(this.bareRepoPath);
|
|
331
|
-
// Try to get branch name before removing worktree
|
|
332
|
-
let branchName = null;
|
|
333
|
-
try {
|
|
334
|
-
const worktrees = await this.getWorktreesFromBare(bareGit);
|
|
335
|
-
const worktree = worktrees.find((w) => path.resolve(w.path) === path.resolve(worktreePath));
|
|
336
|
-
branchName = worktree?.branch || null;
|
|
337
|
-
}
|
|
338
|
-
catch {
|
|
339
|
-
// If we can't get the branch name, extract from path as fallback
|
|
340
|
-
branchName = path.basename(worktreePath);
|
|
341
|
-
}
|
|
342
374
|
await bareGit.raw(["worktree", "remove", worktreePath, "--force"]);
|
|
343
375
|
console.log(` - ✅ Safely removed stale worktree at '${worktreePath}'.`);
|
|
344
|
-
// Clean up metadata
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
console.warn(`Failed to delete metadata for worktree: ${metadataError}`);
|
|
351
|
-
}
|
|
376
|
+
// Clean up metadata using the worktree path
|
|
377
|
+
try {
|
|
378
|
+
await this.metadataService.deleteMetadataFromPath(this.bareRepoPath, worktreePath);
|
|
379
|
+
}
|
|
380
|
+
catch (metadataError) {
|
|
381
|
+
console.warn(`Failed to delete metadata for worktree: ${metadataError}`);
|
|
352
382
|
}
|
|
353
383
|
}
|
|
354
384
|
async pruneWorktrees() {
|
|
@@ -383,8 +413,8 @@ class GitService {
|
|
|
383
413
|
// Check if upstream is gone
|
|
384
414
|
const upstreamGone = await this.hasUpstreamGone(worktreePath);
|
|
385
415
|
if (upstreamGone) {
|
|
386
|
-
// Load metadata to check for commits after last sync
|
|
387
|
-
const metadata = await this.metadataService.
|
|
416
|
+
// Load metadata to check for commits after last sync (use path-based method)
|
|
417
|
+
const metadata = await this.metadataService.loadMetadataFromPath(this.bareRepoPath, worktreePath);
|
|
388
418
|
if (metadata?.lastSyncCommit) {
|
|
389
419
|
try {
|
|
390
420
|
// Check for commits after last sync
|
|
@@ -424,22 +454,38 @@ class GitService {
|
|
|
424
454
|
return !remoteBranches.all.includes(upstream.trim());
|
|
425
455
|
}
|
|
426
456
|
catch (error) {
|
|
427
|
-
|
|
428
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
429
|
-
// Match specific Git error messages for missing upstream
|
|
457
|
+
const errorMessage = (0, lfs_error_1.getErrorMessage)(error);
|
|
430
458
|
if (errorMessage.includes("fatal: no upstream configured") ||
|
|
431
|
-
errorMessage.includes("no upstream configured for branch")
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
459
|
+
errorMessage.includes("no upstream configured for branch")) {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
if (errorMessage.includes("fatal: ambiguous argument") || errorMessage.includes("unknown revision or path")) {
|
|
463
|
+
try {
|
|
464
|
+
const branchSummary = await worktreeGit.branch();
|
|
465
|
+
const currentBranch = branchSummary.current;
|
|
466
|
+
const remoteResult = await worktreeGit
|
|
467
|
+
.raw(["config", "--get", `branch.${currentBranch}.remote`])
|
|
468
|
+
.catch(() => "");
|
|
469
|
+
const mergeResult = await worktreeGit
|
|
470
|
+
.raw(["config", "--get", `branch.${currentBranch}.merge`])
|
|
471
|
+
.catch(() => "");
|
|
472
|
+
const remote = remoteResult.trim();
|
|
473
|
+
const merge = mergeResult.trim();
|
|
474
|
+
if (remote && merge) {
|
|
475
|
+
const remoteBranchName = merge.replace("refs/heads/", "");
|
|
476
|
+
const expectedUpstream = `${remote}/${remoteBranchName}`;
|
|
477
|
+
const remoteBranches = await worktreeGit.branch(["-r"]);
|
|
478
|
+
return !remoteBranches.all.includes(expectedUpstream);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
catch {
|
|
482
|
+
// Can't determine config, be conservative
|
|
483
|
+
}
|
|
435
484
|
return false;
|
|
436
485
|
}
|
|
437
|
-
// Log unexpected errors that don't match known patterns
|
|
438
486
|
console.error(`Unexpected error checking upstream status for ${worktreePath}. ` +
|
|
439
487
|
`This might indicate a real issue rather than a missing upstream. ` +
|
|
440
488
|
`Error: ${errorMessage}`);
|
|
441
|
-
// Return false to be safe - we don't want to accidentally delete worktrees
|
|
442
|
-
// due to transient errors
|
|
443
489
|
return false;
|
|
444
490
|
}
|
|
445
491
|
}
|
|
@@ -582,10 +628,10 @@ class GitService {
|
|
|
582
628
|
if (isMainWorktree) {
|
|
583
629
|
return;
|
|
584
630
|
}
|
|
585
|
-
// Update metadata after successful update
|
|
631
|
+
// Update metadata after successful update (use path-based method)
|
|
586
632
|
try {
|
|
587
633
|
const currentCommit = await worktreeGit.revparse(["HEAD"]);
|
|
588
|
-
await this.metadataService.
|
|
634
|
+
await this.metadataService.updateLastSyncFromPath(this.bareRepoPath, worktreePath, currentCommit.trim(), "updated", this.defaultBranch);
|
|
589
635
|
}
|
|
590
636
|
catch (metadataError) {
|
|
591
637
|
console.warn(`Failed to update metadata for worktree: ${metadataError}`);
|
|
@@ -644,10 +690,10 @@ class GitService {
|
|
|
644
690
|
? (0, simple_git_1.default)(worktreePath).env({ GIT_LFS_SKIP_SMUDGE: "1" })
|
|
645
691
|
: (0, simple_git_1.default)(worktreePath);
|
|
646
692
|
await worktreeGit.reset(["--hard", `origin/${branch}`]);
|
|
647
|
-
// Update metadata after reset
|
|
693
|
+
// Update metadata after reset (use path-based method)
|
|
648
694
|
try {
|
|
649
695
|
const currentCommit = await worktreeGit.revparse(["HEAD"]);
|
|
650
|
-
await this.metadataService.
|
|
696
|
+
await this.metadataService.updateLastSyncFromPath(this.bareRepoPath, worktreePath, currentCommit.trim(), "updated", this.defaultBranch);
|
|
651
697
|
}
|
|
652
698
|
catch (metadataError) {
|
|
653
699
|
console.warn(`Failed to update metadata after reset: ${metadataError}`);
|