sync-worktrees 0.1.1
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/README.md +142 -0
- package/dist/__tests__/fixtures/git-responses.d.ts +114 -0
- package/dist/__tests__/fixtures/git-responses.d.ts.map +1 -0
- package/dist/__tests__/fixtures/git-responses.js +119 -0
- package/dist/__tests__/fixtures/git-responses.js.map +1 -0
- package/dist/__tests__/helpers/mock-helpers.d.ts +29 -0
- package/dist/__tests__/helpers/mock-helpers.d.ts.map +1 -0
- package/dist/__tests__/helpers/mock-helpers.js +82 -0
- package/dist/__tests__/helpers/mock-helpers.js.map +1 -0
- package/dist/__tests__/integration.test.d.ts +2 -0
- package/dist/__tests__/integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration.test.js +225 -0
- package/dist/__tests__/integration.test.js.map +1 -0
- package/dist/__tests__/setup.d.ts +2 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +18 -0
- package/dist/__tests__/setup.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/services/__tests__/git.service.test.d.ts +2 -0
- package/dist/services/__tests__/git.service.test.d.ts.map +1 -0
- package/dist/services/__tests__/git.service.test.js +233 -0
- package/dist/services/__tests__/git.service.test.js.map +1 -0
- package/dist/services/__tests__/worktree-sync.service.test.d.ts +2 -0
- package/dist/services/__tests__/worktree-sync.service.test.d.ts.map +1 -0
- package/dist/services/__tests__/worktree-sync.service.test.js +194 -0
- package/dist/services/__tests__/worktree-sync.service.test.js.map +1 -0
- package/dist/services/git.service.d.ts +17 -0
- package/dist/services/git.service.d.ts.map +1 -0
- package/dist/services/git.service.js +122 -0
- package/dist/services/git.service.js.map +1 -0
- package/dist/services/worktree-sync.service.d.ts +11 -0
- package/dist/services/worktree-sync.service.d.ts.map +1 -0
- package/dist/services/worktree-sync.service.js +124 -0
- package/dist/services/worktree-sync.service.js.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/__tests__/cli.test.d.ts +2 -0
- package/dist/utils/__tests__/cli.test.d.ts.map +1 -0
- package/dist/utils/__tests__/cli.test.js +10 -0
- package/dist/utils/__tests__/cli.test.js.map +1 -0
- package/dist/utils/cli.d.ts +3 -0
- package/dist/utils/cli.d.ts.map +1 -0
- package/dist/utils/cli.js +43 -0
- package/dist/utils/cli.js.map +1 -0
- package/package.json +74 -0
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# sync-worktrees
|
|
2
|
+
|
|
3
|
+
Automatically synchronize Git worktrees with remote branches. Keep your local worktrees in sync with remote repositories - perfect for CI/CD environments, multi-branch development workflows, and automated testing setups.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔄 Automatically creates worktrees for all remote branches
|
|
8
|
+
- 🗑️ Removes worktrees for deleted remote branches (preserves local changes)
|
|
9
|
+
- ⏰ Run as a scheduled cron job or one-time execution
|
|
10
|
+
- 🛡️ Safe operations - won't delete worktrees with uncommitted changes or unpushed commits
|
|
11
|
+
- 📝 Clear logging with timestamps and progress indicators
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g sync-worktrees
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or with pnpm:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm add -g sync-worktrees
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### One-time sync
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
sync-worktrees --repoPath /path/to/repo --worktreeDir /path/to/worktrees --runOnce
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Scheduled sync (default: hourly)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
sync-worktrees --repoPath /path/to/repo --worktreeDir /path/to/worktrees
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Clone and sync a new repository
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
sync-worktrees \
|
|
43
|
+
--repoPath /path/to/repo \
|
|
44
|
+
--repoUrl git@github.com:user/repo.git \
|
|
45
|
+
--worktreeDir /path/to/worktrees \
|
|
46
|
+
--runOnce
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Options
|
|
50
|
+
|
|
51
|
+
| Option | Alias | Description | Required | Default |
|
|
52
|
+
|--------|-------|-------------|----------|---------|
|
|
53
|
+
| `--repoPath` | `-r` | Absolute path to the target repository | Yes | - |
|
|
54
|
+
| `--repoUrl` | `-u` | Git repository URL for cloning | No | - |
|
|
55
|
+
| `--worktreeDir` | `-w` | Directory for storing worktrees | Yes | - |
|
|
56
|
+
| `--cronSchedule` | `-s` | Cron pattern for scheduling | No | `0 * * * *` (hourly) |
|
|
57
|
+
| `--runOnce` | - | Execute once and exit | No | `false` |
|
|
58
|
+
| `--help` | `-h` | Show help | No | - |
|
|
59
|
+
|
|
60
|
+
## Examples
|
|
61
|
+
|
|
62
|
+
### Basic one-time sync
|
|
63
|
+
```bash
|
|
64
|
+
sync-worktrees -r /home/user/my-repo -w /home/user/my-repo-worktrees --runOnce
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Custom cron schedule (every 30 minutes)
|
|
68
|
+
```bash
|
|
69
|
+
sync-worktrees -r /home/user/my-repo -w /home/user/my-repo-worktrees -s "*/30 * * * *"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Clone and sync a repository
|
|
73
|
+
```bash
|
|
74
|
+
sync-worktrees \
|
|
75
|
+
-r /home/user/new-repo \
|
|
76
|
+
-u https://github.com/example/project.git \
|
|
77
|
+
-w /home/user/new-repo-worktrees \
|
|
78
|
+
--runOnce
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## How it works
|
|
82
|
+
|
|
83
|
+
1. **Initialization**: Clones the repository if it doesn't exist (when `--repoUrl` is provided)
|
|
84
|
+
2. **Synchronization**:
|
|
85
|
+
- Fetches latest changes from all remotes
|
|
86
|
+
- Creates worktrees for new remote branches
|
|
87
|
+
- Removes worktrees for deleted remote branches (only if they have no local changes and no unpushed commits)
|
|
88
|
+
- Prunes stale worktree metadata
|
|
89
|
+
|
|
90
|
+
## Requirements
|
|
91
|
+
|
|
92
|
+
- Node.js >= 22.0.0
|
|
93
|
+
- Git
|
|
94
|
+
|
|
95
|
+
## Development
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Clone the repository
|
|
99
|
+
git clone https://github.com/yordan-kanchelov/sync-worktrees.git
|
|
100
|
+
cd sync-worktrees
|
|
101
|
+
|
|
102
|
+
# Install dependencies
|
|
103
|
+
pnpm install
|
|
104
|
+
|
|
105
|
+
# Build
|
|
106
|
+
pnpm build
|
|
107
|
+
|
|
108
|
+
# Run tests
|
|
109
|
+
pnpm test
|
|
110
|
+
|
|
111
|
+
# Development mode
|
|
112
|
+
pnpm dev -- --repoPath /path/to/repo --worktreeDir /path/to/worktrees --runOnce
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Available Scripts
|
|
116
|
+
|
|
117
|
+
- `pnpm build` - Build the project
|
|
118
|
+
- `pnpm dev` - Run in development mode
|
|
119
|
+
- `pnpm test` - Run tests
|
|
120
|
+
- `pnpm lint` - Check linting
|
|
121
|
+
- `pnpm typecheck` - Run type checking
|
|
122
|
+
- `pnpm changeset` - Create a changeset for your changes
|
|
123
|
+
- `pnpm version` - Update versions based on changesets
|
|
124
|
+
- `pnpm release` - Build and publish to npm
|
|
125
|
+
|
|
126
|
+
## Contributing
|
|
127
|
+
|
|
128
|
+
This project uses [changesets](https://github.com/changesets/changesets) to manage versions and releases.
|
|
129
|
+
|
|
130
|
+
### Making Changes
|
|
131
|
+
|
|
132
|
+
1. Make your changes and commit them
|
|
133
|
+
2. Run `pnpm changeset` to create a changeset describing your changes
|
|
134
|
+
3. Select the appropriate version bump type (patch/minor/major)
|
|
135
|
+
4. Write a summary of your changes for the changelog
|
|
136
|
+
5. Commit the generated changeset file
|
|
137
|
+
|
|
138
|
+
The CI will automatically create a PR to update versions when changesets are merged to main, and will publish to npm when that PR is merged.
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
ISC
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common git response fixtures for testing
|
|
3
|
+
*/
|
|
4
|
+
export declare const gitBranchResponses: {
|
|
5
|
+
withMultipleBranches: {
|
|
6
|
+
all: string[];
|
|
7
|
+
current: string;
|
|
8
|
+
branches: {};
|
|
9
|
+
detached: boolean;
|
|
10
|
+
};
|
|
11
|
+
withSingleBranch: {
|
|
12
|
+
all: string[];
|
|
13
|
+
current: string;
|
|
14
|
+
branches: {};
|
|
15
|
+
detached: boolean;
|
|
16
|
+
};
|
|
17
|
+
empty: {
|
|
18
|
+
all: never[];
|
|
19
|
+
current: string;
|
|
20
|
+
branches: {};
|
|
21
|
+
detached: boolean;
|
|
22
|
+
};
|
|
23
|
+
withLocalAndRemote: {
|
|
24
|
+
all: string[];
|
|
25
|
+
current: string;
|
|
26
|
+
branches: {};
|
|
27
|
+
detached: boolean;
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export declare const gitStatusResponses: {
|
|
31
|
+
clean: {
|
|
32
|
+
isClean: () => boolean;
|
|
33
|
+
not_added: never[];
|
|
34
|
+
conflicted: never[];
|
|
35
|
+
created: never[];
|
|
36
|
+
deleted: never[];
|
|
37
|
+
modified: never[];
|
|
38
|
+
renamed: never[];
|
|
39
|
+
files: never[];
|
|
40
|
+
staged: never[];
|
|
41
|
+
ahead: number;
|
|
42
|
+
behind: number;
|
|
43
|
+
current: string;
|
|
44
|
+
tracking: string;
|
|
45
|
+
detached: boolean;
|
|
46
|
+
};
|
|
47
|
+
withChanges: {
|
|
48
|
+
isClean: () => boolean;
|
|
49
|
+
not_added: string[];
|
|
50
|
+
conflicted: never[];
|
|
51
|
+
created: never[];
|
|
52
|
+
deleted: never[];
|
|
53
|
+
modified: string[];
|
|
54
|
+
renamed: never[];
|
|
55
|
+
files: {
|
|
56
|
+
path: string;
|
|
57
|
+
index: string;
|
|
58
|
+
working_dir: string;
|
|
59
|
+
}[];
|
|
60
|
+
staged: never[];
|
|
61
|
+
ahead: number;
|
|
62
|
+
behind: number;
|
|
63
|
+
current: string;
|
|
64
|
+
tracking: string;
|
|
65
|
+
detached: boolean;
|
|
66
|
+
};
|
|
67
|
+
withStagedChanges: {
|
|
68
|
+
isClean: () => boolean;
|
|
69
|
+
not_added: never[];
|
|
70
|
+
conflicted: never[];
|
|
71
|
+
created: string[];
|
|
72
|
+
deleted: never[];
|
|
73
|
+
modified: string[];
|
|
74
|
+
renamed: never[];
|
|
75
|
+
files: {
|
|
76
|
+
path: string;
|
|
77
|
+
index: string;
|
|
78
|
+
working_dir: string;
|
|
79
|
+
}[];
|
|
80
|
+
staged: string[];
|
|
81
|
+
ahead: number;
|
|
82
|
+
behind: number;
|
|
83
|
+
current: string;
|
|
84
|
+
tracking: string;
|
|
85
|
+
detached: boolean;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
export declare const worktreeScenarios: {
|
|
89
|
+
fresh: {
|
|
90
|
+
remoteBranches: string[];
|
|
91
|
+
existingWorktrees: never[];
|
|
92
|
+
expectedNewWorktrees: string[];
|
|
93
|
+
expectedRemovals: never[];
|
|
94
|
+
};
|
|
95
|
+
partial: {
|
|
96
|
+
remoteBranches: string[];
|
|
97
|
+
existingWorktrees: string[];
|
|
98
|
+
expectedNewWorktrees: string[];
|
|
99
|
+
expectedRemovals: never[];
|
|
100
|
+
};
|
|
101
|
+
withStale: {
|
|
102
|
+
remoteBranches: string[];
|
|
103
|
+
existingWorktrees: string[];
|
|
104
|
+
expectedNewWorktrees: never[];
|
|
105
|
+
expectedRemovals: string[];
|
|
106
|
+
};
|
|
107
|
+
mixed: {
|
|
108
|
+
remoteBranches: string[];
|
|
109
|
+
existingWorktrees: string[];
|
|
110
|
+
expectedNewWorktrees: string[];
|
|
111
|
+
expectedRemovals: string[];
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=git-responses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-responses.d.ts","sourceRoot":"","sources":["../../../src/__tests__/fixtures/git-responses.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;CAyB9B,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuD9B,CAAC;AAEF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;CA6B7B,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Common git response fixtures for testing
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.worktreeScenarios = exports.gitStatusResponses = exports.gitBranchResponses = void 0;
|
|
7
|
+
exports.gitBranchResponses = {
|
|
8
|
+
withMultipleBranches: {
|
|
9
|
+
all: ["origin/main", "origin/feature-1", "origin/feature-2", "origin/bugfix/issue-123", "origin/release/v1.0.0"],
|
|
10
|
+
current: "main",
|
|
11
|
+
branches: {},
|
|
12
|
+
detached: false,
|
|
13
|
+
},
|
|
14
|
+
withSingleBranch: {
|
|
15
|
+
all: ["origin/main"],
|
|
16
|
+
current: "main",
|
|
17
|
+
branches: {},
|
|
18
|
+
detached: false,
|
|
19
|
+
},
|
|
20
|
+
empty: {
|
|
21
|
+
all: [],
|
|
22
|
+
current: "",
|
|
23
|
+
branches: {},
|
|
24
|
+
detached: false,
|
|
25
|
+
},
|
|
26
|
+
withLocalAndRemote: {
|
|
27
|
+
all: ["main", "feature-local", "origin/main", "origin/feature-1", "origin/feature-2"],
|
|
28
|
+
current: "main",
|
|
29
|
+
branches: {},
|
|
30
|
+
detached: false,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
exports.gitStatusResponses = {
|
|
34
|
+
clean: {
|
|
35
|
+
isClean: () => true,
|
|
36
|
+
not_added: [],
|
|
37
|
+
conflicted: [],
|
|
38
|
+
created: [],
|
|
39
|
+
deleted: [],
|
|
40
|
+
modified: [],
|
|
41
|
+
renamed: [],
|
|
42
|
+
files: [],
|
|
43
|
+
staged: [],
|
|
44
|
+
ahead: 0,
|
|
45
|
+
behind: 0,
|
|
46
|
+
current: "main",
|
|
47
|
+
tracking: "origin/main",
|
|
48
|
+
detached: false,
|
|
49
|
+
},
|
|
50
|
+
withChanges: {
|
|
51
|
+
isClean: () => false,
|
|
52
|
+
not_added: ["new-file.txt"],
|
|
53
|
+
conflicted: [],
|
|
54
|
+
created: [],
|
|
55
|
+
deleted: [],
|
|
56
|
+
modified: ["existing-file.ts"],
|
|
57
|
+
renamed: [],
|
|
58
|
+
files: [
|
|
59
|
+
{ path: "new-file.txt", index: "?", working_dir: "?" },
|
|
60
|
+
{ path: "existing-file.ts", index: " ", working_dir: "M" },
|
|
61
|
+
],
|
|
62
|
+
staged: [],
|
|
63
|
+
ahead: 0,
|
|
64
|
+
behind: 0,
|
|
65
|
+
current: "feature-1",
|
|
66
|
+
tracking: "origin/feature-1",
|
|
67
|
+
detached: false,
|
|
68
|
+
},
|
|
69
|
+
withStagedChanges: {
|
|
70
|
+
isClean: () => false,
|
|
71
|
+
not_added: [],
|
|
72
|
+
conflicted: [],
|
|
73
|
+
created: ["new-file.txt"],
|
|
74
|
+
deleted: [],
|
|
75
|
+
modified: ["existing-file.ts"],
|
|
76
|
+
renamed: [],
|
|
77
|
+
files: [
|
|
78
|
+
{ path: "new-file.txt", index: "A", working_dir: " " },
|
|
79
|
+
{ path: "existing-file.ts", index: "M", working_dir: " " },
|
|
80
|
+
],
|
|
81
|
+
staged: ["new-file.txt", "existing-file.ts"],
|
|
82
|
+
ahead: 1,
|
|
83
|
+
behind: 0,
|
|
84
|
+
current: "feature-1",
|
|
85
|
+
tracking: "origin/feature-1",
|
|
86
|
+
detached: false,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
exports.worktreeScenarios = {
|
|
90
|
+
// Scenario: Fresh repository with no worktrees
|
|
91
|
+
fresh: {
|
|
92
|
+
remoteBranches: ["main", "develop", "feature-1"],
|
|
93
|
+
existingWorktrees: [],
|
|
94
|
+
expectedNewWorktrees: ["main", "develop", "feature-1"],
|
|
95
|
+
expectedRemovals: [],
|
|
96
|
+
},
|
|
97
|
+
// Scenario: Some worktrees already exist
|
|
98
|
+
partial: {
|
|
99
|
+
remoteBranches: ["main", "develop", "feature-1", "feature-2"],
|
|
100
|
+
existingWorktrees: ["main", "develop"],
|
|
101
|
+
expectedNewWorktrees: ["feature-1", "feature-2"],
|
|
102
|
+
expectedRemovals: [],
|
|
103
|
+
},
|
|
104
|
+
// Scenario: Need to prune old worktrees
|
|
105
|
+
withStale: {
|
|
106
|
+
remoteBranches: ["main", "develop"],
|
|
107
|
+
existingWorktrees: ["main", "develop", "old-feature", "deleted-branch"],
|
|
108
|
+
expectedNewWorktrees: [],
|
|
109
|
+
expectedRemovals: ["old-feature", "deleted-branch"],
|
|
110
|
+
},
|
|
111
|
+
// Scenario: Mixed - add new and remove old
|
|
112
|
+
mixed: {
|
|
113
|
+
remoteBranches: ["main", "develop", "new-feature"],
|
|
114
|
+
existingWorktrees: ["main", "old-feature"],
|
|
115
|
+
expectedNewWorktrees: ["develop", "new-feature"],
|
|
116
|
+
expectedRemovals: ["old-feature"],
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=git-responses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-responses.js","sourceRoot":"","sources":["../../../src/__tests__/fixtures/git-responses.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jest } from "@jest/globals";
|
|
2
|
+
import type { SimpleGit } from "simple-git";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a mock SimpleGit instance with common default behaviors
|
|
5
|
+
*/
|
|
6
|
+
export declare function createMockGit(overrides?: Partial<SimpleGit>): jest.Mocked<SimpleGit>;
|
|
7
|
+
/**
|
|
8
|
+
* Creates a mock file system structure for testing
|
|
9
|
+
*/
|
|
10
|
+
export interface MockFileSystem {
|
|
11
|
+
[path: string]: {
|
|
12
|
+
type: "file" | "directory";
|
|
13
|
+
content?: string;
|
|
14
|
+
children?: string[];
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Sets up fs.promises mocks based on a mock file system structure
|
|
19
|
+
*/
|
|
20
|
+
export declare function setupMockFileSystem(mockFs: MockFileSystem, fsMock: {
|
|
21
|
+
access: jest.Mock<any>;
|
|
22
|
+
readdir: jest.Mock<any>;
|
|
23
|
+
mkdir: jest.Mock<any>;
|
|
24
|
+
}): void;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a test configuration object
|
|
27
|
+
*/
|
|
28
|
+
export declare function createTestConfig(overrides?: any): any;
|
|
29
|
+
//# sourceMappingURL=mock-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-helpers.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/mock-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CA6BpF;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,CAAC,IAAI,EAAE,MAAM,GAAG;QACd,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;QAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE;IACN,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;CACvB,GACA,IAAI,CA2BN;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,GAAG,OAS/C"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createMockGit = createMockGit;
|
|
4
|
+
exports.setupMockFileSystem = setupMockFileSystem;
|
|
5
|
+
exports.createTestConfig = createTestConfig;
|
|
6
|
+
const globals_1 = require("@jest/globals");
|
|
7
|
+
/**
|
|
8
|
+
* Creates a mock SimpleGit instance with common default behaviors
|
|
9
|
+
*/
|
|
10
|
+
function createMockGit(overrides) {
|
|
11
|
+
return {
|
|
12
|
+
fetch: globals_1.jest.fn().mockResolvedValue(undefined),
|
|
13
|
+
branch: globals_1.jest.fn().mockResolvedValue({
|
|
14
|
+
all: ["origin/main"],
|
|
15
|
+
current: "main",
|
|
16
|
+
branches: {},
|
|
17
|
+
detached: false,
|
|
18
|
+
}),
|
|
19
|
+
raw: globals_1.jest.fn().mockResolvedValue(""),
|
|
20
|
+
status: globals_1.jest.fn().mockResolvedValue({
|
|
21
|
+
isClean: globals_1.jest.fn().mockReturnValue(true),
|
|
22
|
+
not_added: [],
|
|
23
|
+
conflicted: [],
|
|
24
|
+
created: [],
|
|
25
|
+
deleted: [],
|
|
26
|
+
modified: [],
|
|
27
|
+
renamed: [],
|
|
28
|
+
files: [],
|
|
29
|
+
staged: [],
|
|
30
|
+
ahead: 0,
|
|
31
|
+
behind: 0,
|
|
32
|
+
current: "main",
|
|
33
|
+
tracking: "origin/main",
|
|
34
|
+
detached: false,
|
|
35
|
+
}),
|
|
36
|
+
clone: globals_1.jest.fn().mockResolvedValue(undefined),
|
|
37
|
+
...overrides,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Sets up fs.promises mocks based on a mock file system structure
|
|
42
|
+
*/
|
|
43
|
+
function setupMockFileSystem(mockFs, fsMock) {
|
|
44
|
+
// Mock fs.access
|
|
45
|
+
fsMock.access.mockImplementation(async (path) => {
|
|
46
|
+
if (!(path in mockFs)) {
|
|
47
|
+
throw new Error(`ENOENT: no such file or directory, access '${path}'`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
// Mock fs.readdir
|
|
51
|
+
fsMock.readdir.mockImplementation(async (path) => {
|
|
52
|
+
const entry = mockFs[path];
|
|
53
|
+
if (!entry) {
|
|
54
|
+
throw new Error(`ENOENT: no such file or directory, scandir '${path}'`);
|
|
55
|
+
}
|
|
56
|
+
if (entry.type !== "directory") {
|
|
57
|
+
throw new Error(`ENOTDIR: not a directory, scandir '${path}'`);
|
|
58
|
+
}
|
|
59
|
+
return entry.children || [];
|
|
60
|
+
});
|
|
61
|
+
// Mock fs.mkdir
|
|
62
|
+
fsMock.mkdir.mockImplementation(async (path, options) => {
|
|
63
|
+
if (path in mockFs && !options?.recursive) {
|
|
64
|
+
throw new Error(`EEXIST: file already exists, mkdir '${path}'`);
|
|
65
|
+
}
|
|
66
|
+
mockFs[path] = { type: "directory", children: [] };
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Creates a test configuration object
|
|
71
|
+
*/
|
|
72
|
+
function createTestConfig(overrides) {
|
|
73
|
+
return {
|
|
74
|
+
repoPath: "/test/repo",
|
|
75
|
+
repoUrl: "https://github.com/test/repo.git",
|
|
76
|
+
worktreeDir: "/test/worktrees",
|
|
77
|
+
cronSchedule: "0 * * * *",
|
|
78
|
+
runOnce: false,
|
|
79
|
+
...overrides,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=mock-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-helpers.js","sourceRoot":"","sources":["../../../src/__tests__/helpers/mock-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/integration.test.ts"],"names":[],"mappings":""}
|