@wipzent/github-sync 1.0.3 → 1.0.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/LICENSE +10 -17
- package/README.md +1 -1
- package/dist/cli/index.js +37 -32
- package/dist/cli/prompts.js +9 -3
- package/dist/config/defaults.js +4 -1
- package/dist/config/env.js +9 -3
- package/dist/config/octokit.js +12 -8
- package/dist/git/clone.js +8 -5
- package/dist/git/rewriteAuthor.js +6 -3
- package/dist/git/sync.js +15 -11
- package/dist/mcp/resources/github.js +9 -5
- package/dist/mcp/server.js +16 -14
- package/dist/mcp/tools/autoSync.js +44 -38
- package/dist/mcp/tools/createRepo.js +32 -26
- package/dist/mcp/tools/resolveConflict.js +4 -1
- package/dist/mcp/tools/syncRepo.js +13 -7
- package/package.json +11 -10
package/LICENSE
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
Proprietary License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026 Wipzent
|
|
3
|
+
Copyright (c) 2026 Wipzent. All rights reserved.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
5
|
+
Commercial use, reproduction, or distribution of this software, in whole or in part,
|
|
6
|
+
is strictly prohibited without the express written permission of Wipzent.
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
You may use this software for its intended purpose as a synchronization tool,
|
|
9
|
+
but you are NOT permitted to:
|
|
10
|
+
1. Copy the source code for redistribution.
|
|
11
|
+
2. Build derivative products for resale.
|
|
12
|
+
3. Remove or alter any copyright notices.
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
14
|
+
For licensing inquiries, contact engineering@wipzent.com.
|
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ npx @wipzent/github-sync sync <repo-name>
|
|
|
36
36
|
#### 1. Sync a Repository
|
|
37
37
|
Automatically sync a personal repo to an organization mirror:
|
|
38
38
|
```bash
|
|
39
|
-
wipzent-sync sync
|
|
39
|
+
wipzent-sync sync clientUsername/clientRepoName
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
#### 2. Manual Setup
|
package/dist/cli/index.js
CHANGED
|
@@ -1,44 +1,49 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const syncRepo_js_1 = require("../mcp/tools/syncRepo.js");
|
|
9
|
+
const createRepo_js_1 = require("../mcp/tools/createRepo.js");
|
|
10
|
+
const autoSync_js_1 = require("../mcp/tools/autoSync.js");
|
|
11
|
+
const sync_js_1 = require("../git/sync.js");
|
|
12
|
+
const fs_1 = __importDefault(require("fs"));
|
|
13
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
14
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
15
|
+
const program = new commander_1.Command();
|
|
11
16
|
program
|
|
12
17
|
.name('mcp-github-sync')
|
|
13
18
|
.description('CLI for GitHub repository synchronization')
|
|
14
19
|
.version('1.0.0');
|
|
15
20
|
async function promptRewrite() {
|
|
16
|
-
const { shouldRewrite } = await
|
|
21
|
+
const { shouldRewrite } = await inquirer_1.default.prompt([
|
|
17
22
|
{
|
|
18
23
|
type: 'confirm',
|
|
19
24
|
name: 'shouldRewrite',
|
|
20
|
-
message:
|
|
25
|
+
message: chalk_1.default.yellow('Do you want to normalize Git history/author to your personal account?'),
|
|
21
26
|
default: false
|
|
22
27
|
}
|
|
23
28
|
]);
|
|
24
29
|
return shouldRewrite;
|
|
25
30
|
}
|
|
26
31
|
async function handleDivergence(personal, org, owner, shouldRewrite, isAutoSync = true) {
|
|
27
|
-
const { action } = await
|
|
32
|
+
const { action } = await inquirer_1.default.prompt([
|
|
28
33
|
{
|
|
29
34
|
type: 'list',
|
|
30
35
|
name: 'action',
|
|
31
|
-
message:
|
|
36
|
+
message: chalk_1.default.red.bold('Conflict: ') + chalk_1.default.white('The organization repository contains changes not in your local/personal repo. How to proceed?'),
|
|
32
37
|
choices: [
|
|
33
|
-
{ name:
|
|
34
|
-
{ name:
|
|
35
|
-
{ name:
|
|
38
|
+
{ name: chalk_1.default.green('Pull & Merge: ') + 'Integrate org changes and resolve locally (Safest)', value: 'merge' },
|
|
39
|
+
{ name: chalk_1.default.red('Overwrite Organization: ') + 'Force push local repo to organization (USE WITH CAUTION)', value: 'force' },
|
|
40
|
+
{ name: chalk_1.default.magenta('Overwrite Personal: ') + 'Force push org content to personal repo (Sync Org -> Personal)', value: 'overwrite-personal' },
|
|
36
41
|
{ name: 'Abort', value: 'abort' }
|
|
37
42
|
]
|
|
38
43
|
}
|
|
39
44
|
]);
|
|
40
45
|
if (action === 'abort') {
|
|
41
|
-
console.log(
|
|
46
|
+
console.log(chalk_1.default.gray('Sync aborted by user.'));
|
|
42
47
|
return;
|
|
43
48
|
}
|
|
44
49
|
const forcePush = action === 'force';
|
|
@@ -46,7 +51,7 @@ async function handleDivergence(personal, org, owner, shouldRewrite, isAutoSync
|
|
|
46
51
|
const overwriteSource = action === 'overwrite-personal';
|
|
47
52
|
if (isAutoSync) {
|
|
48
53
|
console.log(`🚀 Continuing auto-sync with resolution: ${action}...`);
|
|
49
|
-
const result = await autoSync(personal, shouldRewrite, forcePush, pullChanges, overwriteSource, true);
|
|
54
|
+
const result = await (0, autoSync_js_1.autoSync)(personal, shouldRewrite, forcePush, pullChanges, overwriteSource, true);
|
|
50
55
|
if (result.success && result.pendingPushes?.length) {
|
|
51
56
|
await handlePushes(result.localPath, result.pendingPushes);
|
|
52
57
|
}
|
|
@@ -56,7 +61,7 @@ async function handleDivergence(personal, org, owner, shouldRewrite, isAutoSync
|
|
|
56
61
|
}
|
|
57
62
|
else {
|
|
58
63
|
console.log(`🚀 Continuing sync with resolution: ${action}...`);
|
|
59
|
-
const result = await syncRepo(personal, org, shouldRewrite, forcePush, overwriteSource, true);
|
|
64
|
+
const result = await (0, syncRepo_js_1.syncRepo)(personal, org, shouldRewrite, forcePush, overwriteSource, true);
|
|
60
65
|
if (result.success && result.pendingPushes?.length) {
|
|
61
66
|
await handlePushes(result.localPath, result.pendingPushes);
|
|
62
67
|
}
|
|
@@ -67,20 +72,20 @@ async function handleDivergence(personal, org, owner, shouldRewrite, isAutoSync
|
|
|
67
72
|
}
|
|
68
73
|
async function handlePushes(localPath, pushes) {
|
|
69
74
|
if (pushes.length === 0) {
|
|
70
|
-
console.log(
|
|
75
|
+
console.log(chalk_1.default.gray('No pushes pending.'));
|
|
71
76
|
cleanLocal(localPath);
|
|
72
77
|
return;
|
|
73
78
|
}
|
|
74
|
-
const { selectedPushes } = await
|
|
79
|
+
const { selectedPushes } = await inquirer_1.default.prompt([
|
|
75
80
|
{
|
|
76
81
|
type: 'checkbox',
|
|
77
82
|
name: 'selectedPushes',
|
|
78
|
-
message:
|
|
83
|
+
message: chalk_1.default.cyan.bold('Review and Select Push Targets') + chalk_1.default.gray(' (SPACE to select, ENTER to confirm):'),
|
|
79
84
|
choices: pushes.map(p => {
|
|
80
85
|
const isOrg = p.description.includes('Organization');
|
|
81
86
|
const isDanger = p.description.includes('HISTORY REWRITE');
|
|
82
|
-
const remoteLabel = isOrg ?
|
|
83
|
-
const forceLabel = p.force ?
|
|
87
|
+
const remoteLabel = isOrg ? chalk_1.default.magenta.bold('ORG') : chalk_1.default.blue.bold('SRC');
|
|
88
|
+
const forceLabel = p.force ? chalk_1.default.red.bold(' [FORCE]') : '';
|
|
84
89
|
return {
|
|
85
90
|
name: `${remoteLabel} | ${p.description}${forceLabel}`,
|
|
86
91
|
value: p,
|
|
@@ -92,20 +97,20 @@ async function handlePushes(localPath, pushes) {
|
|
|
92
97
|
}
|
|
93
98
|
]);
|
|
94
99
|
if (selectedPushes.length === 0) {
|
|
95
|
-
console.log(
|
|
100
|
+
console.log(chalk_1.default.yellow('Pushes cancelled by user.'));
|
|
96
101
|
}
|
|
97
102
|
else {
|
|
98
103
|
for (const push of selectedPushes) {
|
|
99
|
-
await pushToRemote(localPath, push.remote, push.branch, push.force);
|
|
104
|
+
await (0, sync_js_1.pushToRemote)(localPath, push.remote, push.branch, push.force);
|
|
100
105
|
}
|
|
101
|
-
console.log(
|
|
106
|
+
console.log(chalk_1.default.green.bold('\nSync completed successfully!'));
|
|
102
107
|
}
|
|
103
108
|
cleanLocal(localPath);
|
|
104
109
|
}
|
|
105
110
|
function cleanLocal(localPath) {
|
|
106
|
-
if (
|
|
111
|
+
if (fs_1.default.existsSync(localPath)) {
|
|
107
112
|
try {
|
|
108
|
-
|
|
113
|
+
fs_1.default.rmSync(localPath, { recursive: true, force: true });
|
|
109
114
|
}
|
|
110
115
|
catch (e) {
|
|
111
116
|
// Ignore
|
|
@@ -122,7 +127,7 @@ program
|
|
|
122
127
|
const shouldRewrite = await promptRewrite();
|
|
123
128
|
if (org) {
|
|
124
129
|
console.log(`🚀 Starting sync: ${personal} -> ${org}`);
|
|
125
|
-
const result = await syncRepo(personal, org, shouldRewrite, false, false, true);
|
|
130
|
+
const result = await (0, syncRepo_js_1.syncRepo)(personal, org, shouldRewrite, false, false, true);
|
|
126
131
|
if (result.isDiverged) {
|
|
127
132
|
await handleDivergence(personal, org, '', shouldRewrite, false);
|
|
128
133
|
}
|
|
@@ -137,7 +142,7 @@ program
|
|
|
137
142
|
}
|
|
138
143
|
else {
|
|
139
144
|
console.log(`🚀 Starting auto-sync for: ${personal}`);
|
|
140
|
-
const result = await autoSync(personal, shouldRewrite, false, false, false, true);
|
|
145
|
+
const result = await (0, autoSync_js_1.autoSync)(personal, shouldRewrite, false, false, false, true);
|
|
141
146
|
if (result.isDiverged) {
|
|
142
147
|
await handleDivergence(personal, '', '', shouldRewrite, true);
|
|
143
148
|
}
|
|
@@ -165,7 +170,7 @@ program
|
|
|
165
170
|
try {
|
|
166
171
|
const shouldRewrite = await promptRewrite();
|
|
167
172
|
console.log(`🚀 Starting setup: ${personal} -> ${org}`);
|
|
168
|
-
const result = await createRepo(personal, org, owner, shouldRewrite, false, false, true);
|
|
173
|
+
const result = await (0, createRepo_js_1.createRepo)(personal, org, owner, shouldRewrite, false, false, true);
|
|
169
174
|
if (result.isDiverged) {
|
|
170
175
|
await handleDivergence(personal, org, owner, shouldRewrite, false);
|
|
171
176
|
}
|
package/dist/cli/prompts.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.promptForConflictResolution = promptForConflictResolution;
|
|
7
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
|
+
async function promptForConflictResolution(fileName) {
|
|
9
|
+
const answers = await inquirer_1.default.prompt([
|
|
4
10
|
{
|
|
5
11
|
type: 'list',
|
|
6
12
|
name: 'resolution',
|
package/dist/config/defaults.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaults = void 0;
|
|
4
|
+
exports.defaults = {
|
|
2
5
|
syncInterval: 300, // seconds
|
|
3
6
|
conflictStrategy: 'ask', // 'ask' | 'personal' | 'org'
|
|
4
7
|
logLevel: 'info',
|
package/dist/config/env.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.config = void 0;
|
|
7
|
+
const dotenv_1 = __importDefault(require("dotenv"));
|
|
8
|
+
dotenv_1.default.config();
|
|
3
9
|
const requiredEnvVars = [
|
|
4
10
|
'GITHUB_PERSONAL_PAT',
|
|
5
11
|
'GITHUB_ORG_PAT',
|
|
@@ -13,7 +19,7 @@ requiredEnvVars.forEach((varName) => {
|
|
|
13
19
|
throw new Error(`Environment variable ${varName} is missing or has a placeholder value in .env`);
|
|
14
20
|
}
|
|
15
21
|
});
|
|
16
|
-
|
|
22
|
+
exports.config = {
|
|
17
23
|
personalPat: process.env.GITHUB_PERSONAL_PAT,
|
|
18
24
|
orgPat: process.env.GITHUB_ORG_PAT,
|
|
19
25
|
orgName: process.env.GITHUB_ORG_NAME,
|
package/dist/config/octokit.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.orgOctokit = exports.personalOctokit = void 0;
|
|
4
|
+
exports.getOctokit = getOctokit;
|
|
5
|
+
const octokit_1 = require("octokit");
|
|
6
|
+
const env_js_1 = require("./env.js");
|
|
7
|
+
exports.personalOctokit = new octokit_1.Octokit({
|
|
8
|
+
auth: env_js_1.config.personalPat,
|
|
5
9
|
});
|
|
6
|
-
|
|
7
|
-
auth: config.orgPat,
|
|
10
|
+
exports.orgOctokit = new octokit_1.Octokit({
|
|
11
|
+
auth: env_js_1.config.orgPat,
|
|
8
12
|
});
|
|
9
13
|
/**
|
|
10
14
|
* Utility to get Octokit client based on context
|
|
11
15
|
*/
|
|
12
|
-
|
|
13
|
-
return context === 'personal' ? personalOctokit : orgOctokit;
|
|
16
|
+
function getOctokit(context) {
|
|
17
|
+
return context === 'personal' ? exports.personalOctokit : exports.orgOctokit;
|
|
14
18
|
}
|
package/dist/git/clone.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cloneRepo = cloneRepo;
|
|
4
|
+
const simple_git_1 = require("simple-git");
|
|
5
|
+
const env_js_1 = require("../config/env.js");
|
|
3
6
|
/**
|
|
4
7
|
* Clones a repository using an authenticated URL.
|
|
5
8
|
*
|
|
@@ -7,9 +10,9 @@ import { config } from '../config/env.js';
|
|
|
7
10
|
* @param repo Repository name
|
|
8
11
|
* @param destination Local directory path to clone into
|
|
9
12
|
*/
|
|
10
|
-
|
|
11
|
-
const git = simpleGit();
|
|
13
|
+
async function cloneRepo(owner, repo, destination) {
|
|
14
|
+
const git = (0, simple_git_1.simpleGit)();
|
|
12
15
|
// Construct authenticated URL: https://<token>@github.com/<owner>/<repo>.git
|
|
13
|
-
const authUrl = `https://${config.personalPat}@github.com/${owner}/${repo}.git`;
|
|
16
|
+
const authUrl = `https://${env_js_1.config.personalPat}@github.com/${owner}/${repo}.git`;
|
|
14
17
|
await git.clone(authUrl, destination);
|
|
15
18
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rewriteHistory = rewriteHistory;
|
|
4
|
+
const simple_git_1 = require("simple-git");
|
|
2
5
|
/**
|
|
3
6
|
* Rewrites the entire git history of a repository to a single author/email.
|
|
4
7
|
* USES git filter-branch --env-filter.
|
|
@@ -7,8 +10,8 @@ import { simpleGit } from 'simple-git';
|
|
|
7
10
|
* @param name New author name
|
|
8
11
|
* @param email New author email
|
|
9
12
|
*/
|
|
10
|
-
|
|
11
|
-
const git = simpleGit(path);
|
|
13
|
+
async function rewriteHistory(path, name, email) {
|
|
14
|
+
const git = (0, simple_git_1.simpleGit)(path);
|
|
12
15
|
console.log(`Rewriting history in ${path} to author: ${name} <${email}>...`);
|
|
13
16
|
// Using git filter-branch --env-filter to rewrite all commits
|
|
14
17
|
// This script replaces GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, GIT_COMMITTER_NAME, and GIT_COMMITTER_EMAIL for every commit.
|
package/dist/git/sync.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.syncBetweenRemotes = syncBetweenRemotes;
|
|
4
|
+
exports.pushToRemote = pushToRemote;
|
|
5
|
+
const simple_git_1 = require("simple-git");
|
|
6
|
+
const env_js_1 = require("../config/env.js");
|
|
7
|
+
const rewriteAuthor_js_1 = require("./rewriteAuthor.js");
|
|
4
8
|
/**
|
|
5
9
|
* Performs a safe two-way synchronization between two remotes.
|
|
6
10
|
* 1. Fetches both sources.
|
|
7
11
|
* 2. Attempts a clean merge from source into local (target).
|
|
8
12
|
* 3. Reports conflicts instead of auto-committing messy code.
|
|
9
13
|
*/
|
|
10
|
-
|
|
11
|
-
const git = simpleGit(localPath);
|
|
12
|
-
const branch = config.defaultBranch;
|
|
14
|
+
async function syncBetweenRemotes(localPath, sourceRemote, targetRemote, shouldRewrite = false, forcePush = false, overwriteSource = false, skipPush = false) {
|
|
15
|
+
const git = (0, simple_git_1.simpleGit)(localPath);
|
|
16
|
+
const branch = env_js_1.config.defaultBranch;
|
|
13
17
|
// 1. Fetch latest from both remotes to see state
|
|
14
18
|
await git.fetch(sourceRemote, branch);
|
|
15
19
|
await git.fetch(targetRemote, branch);
|
|
@@ -36,8 +40,8 @@ export async function syncBetweenRemotes(localPath, sourceRemote, targetRemote,
|
|
|
36
40
|
await git.reset(['--hard', `${targetRemote}/${branch}`]);
|
|
37
41
|
// 4. Set local author identity for the synchronization commit
|
|
38
42
|
// This is ALWAYS set to ensure the merge commit is correctly attributed
|
|
39
|
-
await git.addConfig('user.name', config.authorName);
|
|
40
|
-
await git.addConfig('user.email', config.authorEmail);
|
|
43
|
+
await git.addConfig('user.name', env_js_1.config.authorName);
|
|
44
|
+
await git.addConfig('user.email', env_js_1.config.authorEmail);
|
|
41
45
|
// 5. Try to merge changes from sourceRemote unless we are overwriting it
|
|
42
46
|
try {
|
|
43
47
|
if (!overwriteSource) {
|
|
@@ -55,7 +59,7 @@ export async function syncBetweenRemotes(localPath, sourceRemote, targetRemote,
|
|
|
55
59
|
}
|
|
56
60
|
// REWRITE HISTORY AFTER MERGE COMMIT
|
|
57
61
|
if (shouldRewrite) {
|
|
58
|
-
await rewriteHistory(localPath, config.authorName, config.authorEmail);
|
|
62
|
+
await (0, rewriteAuthor_js_1.rewriteHistory)(localPath, env_js_1.config.authorName, env_js_1.config.authorEmail);
|
|
59
63
|
// Force push is REQUIRED if we rewrite history as SHAs change
|
|
60
64
|
forcePush = true;
|
|
61
65
|
}
|
|
@@ -134,8 +138,8 @@ export async function syncBetweenRemotes(localPath, sourceRemote, targetRemote,
|
|
|
134
138
|
/**
|
|
135
139
|
* Executes a Git push to a specific remote and branch.
|
|
136
140
|
*/
|
|
137
|
-
|
|
138
|
-
const git = simpleGit(localPath);
|
|
141
|
+
async function pushToRemote(localPath, remote, branch, force = false) {
|
|
142
|
+
const git = (0, simple_git_1.simpleGit)(localPath);
|
|
139
143
|
console.log(`Pushing to ${remote}/${branch}${force ? ' (FORCE)' : ''}...`);
|
|
140
144
|
await git.push(remote, branch, force ? ['--force'] : []);
|
|
141
145
|
}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GitHubClient = void 0;
|
|
4
|
+
const octokit_1 = require("octokit");
|
|
5
|
+
const env_js_1 = require("../../config/env.js");
|
|
6
|
+
class GitHubClient {
|
|
4
7
|
personalOctokit;
|
|
5
8
|
orgOctokit;
|
|
6
9
|
constructor() {
|
|
7
|
-
this.personalOctokit = new Octokit({ auth: config.personalPat });
|
|
8
|
-
this.orgOctokit = new Octokit({ auth: config.orgPat });
|
|
10
|
+
this.personalOctokit = new octokit_1.Octokit({ auth: env_js_1.config.personalPat });
|
|
11
|
+
this.orgOctokit = new octokit_1.Octokit({ auth: env_js_1.config.orgPat });
|
|
9
12
|
}
|
|
10
13
|
async getRepo(owner, repo) {
|
|
11
14
|
// API call
|
|
12
15
|
}
|
|
13
16
|
}
|
|
17
|
+
exports.GitHubClient = GitHubClient;
|
package/dist/mcp/server.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
4
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
5
|
+
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
6
|
+
const server = new index_js_1.Server({
|
|
5
7
|
name: "mcp-github-sync",
|
|
6
8
|
version: "1.0.0",
|
|
7
9
|
}, {
|
|
@@ -9,10 +11,10 @@ const server = new Server({
|
|
|
9
11
|
tools: {},
|
|
10
12
|
},
|
|
11
13
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
14
|
+
const createRepo_js_1 = require("./tools/createRepo.js");
|
|
15
|
+
const syncRepo_js_1 = require("./tools/syncRepo.js");
|
|
16
|
+
const autoSync_js_1 = require("./tools/autoSync.js");
|
|
17
|
+
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
16
18
|
tools: [
|
|
17
19
|
{
|
|
18
20
|
name: "auto_sync",
|
|
@@ -52,26 +54,26 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
52
54
|
},
|
|
53
55
|
],
|
|
54
56
|
}));
|
|
55
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
57
|
+
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
56
58
|
try {
|
|
57
59
|
switch (request.params.name) {
|
|
58
60
|
case "auto_sync": {
|
|
59
61
|
const args = request.params.arguments;
|
|
60
|
-
const result = await autoSync(args.personalRepoName);
|
|
62
|
+
const result = await (0, autoSync_js_1.autoSync)(args.personalRepoName);
|
|
61
63
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
62
64
|
}
|
|
63
65
|
case "create_repo": {
|
|
64
66
|
const args = request.params.arguments;
|
|
65
|
-
const result = await createRepo(args.personalRepoName, args.orgRepoName, args.owner);
|
|
67
|
+
const result = await (0, createRepo_js_1.createRepo)(args.personalRepoName, args.orgRepoName, args.owner);
|
|
66
68
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
67
69
|
}
|
|
68
70
|
case "sync_repo": {
|
|
69
71
|
const args = request.params.arguments;
|
|
70
|
-
const result = await syncRepo(args.personalRepoName, args.orgRepoName);
|
|
72
|
+
const result = await (0, syncRepo_js_1.syncRepo)(args.personalRepoName, args.orgRepoName);
|
|
71
73
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
72
74
|
}
|
|
73
75
|
default:
|
|
74
|
-
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
|
|
76
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`);
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
catch (error) {
|
|
@@ -82,7 +84,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
82
84
|
}
|
|
83
85
|
});
|
|
84
86
|
async function main() {
|
|
85
|
-
const transport = new StdioServerTransport();
|
|
87
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
86
88
|
await server.connect(transport);
|
|
87
89
|
console.error("MCP GitHub Sync Server running on stdio");
|
|
88
90
|
}
|
|
@@ -1,22 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.autoSync = autoSync;
|
|
7
|
+
const octokit_js_1 = require("../../config/octokit.js");
|
|
8
|
+
const env_js_1 = require("../../config/env.js");
|
|
9
|
+
const createRepo_js_1 = require("./createRepo.js");
|
|
10
|
+
const syncRepo_js_1 = require("./syncRepo.js");
|
|
11
|
+
const fs_1 = __importDefault(require("fs"));
|
|
12
|
+
const path_1 = __importDefault(require("path"));
|
|
13
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
14
|
+
const ora_1 = __importDefault(require("ora"));
|
|
15
|
+
const boxen_1 = __importDefault(require("boxen"));
|
|
10
16
|
/**
|
|
11
17
|
* Automatically handles the check-create-sync workflow for personal or collaborator repos.
|
|
12
18
|
*
|
|
13
19
|
* @param fullRepoName The name of the repository (e.g., 'my-repo' or 'client-owner/client-repo')
|
|
14
20
|
*/
|
|
15
|
-
|
|
16
|
-
const spinner =
|
|
21
|
+
async function autoSync(fullRepoName, shouldRewrite = false, forcePush = false, pullChanges = false, overwriteSource = false, skipPush = false) {
|
|
22
|
+
const spinner = (0, ora_1.default)();
|
|
17
23
|
// Header for the action
|
|
18
|
-
console.log(
|
|
19
|
-
|
|
24
|
+
console.log((0, boxen_1.default)(chalk_1.default.cyan.bold('WIPZENT SYNC') + ' ' + chalk_1.default.gray('v1.0.1') + '\n' +
|
|
25
|
+
chalk_1.default.gray('Source: ') + chalk_1.default.white.bold(fullRepoName), { padding: 1, margin: { top: 1, bottom: 0 }, borderStyle: 'round', borderColor: 'cyan' }));
|
|
20
26
|
// Handle 'owner/repo' format for collaborators/clients
|
|
21
27
|
let owner;
|
|
22
28
|
let repoName;
|
|
@@ -27,7 +33,7 @@ export async function autoSync(fullRepoName, shouldRewrite = false, forcePush =
|
|
|
27
33
|
}
|
|
28
34
|
else {
|
|
29
35
|
// Fallback to authenticated user if only name provided
|
|
30
|
-
const { data: user } = await personalOctokit.rest.users.getAuthenticated();
|
|
36
|
+
const { data: user } = await octokit_js_1.personalOctokit.rest.users.getAuthenticated();
|
|
31
37
|
owner = user.login;
|
|
32
38
|
repoName = parts[0] || fullRepoName;
|
|
33
39
|
}
|
|
@@ -35,36 +41,36 @@ export async function autoSync(fullRepoName, shouldRewrite = false, forcePush =
|
|
|
35
41
|
repoName = repoName.replace(/\.git$/, '').replace(/\/$/, '');
|
|
36
42
|
const orgRepoName = repoName;
|
|
37
43
|
const localDirName = repoName; // Local storage name
|
|
38
|
-
const localPath =
|
|
44
|
+
const localPath = path_1.default.join(process.cwd(), 'temp', localDirName);
|
|
39
45
|
try {
|
|
40
46
|
// 1. Check if repo exists in the organization
|
|
41
|
-
spinner.start(`Verifying ${
|
|
47
|
+
spinner.start(`Verifying ${chalk_1.default.bold(orgRepoName)} in ${chalk_1.default.bold(env_js_1.config.orgName)}...`);
|
|
42
48
|
let exists = false;
|
|
43
49
|
try {
|
|
44
|
-
await orgOctokit.rest.repos.get({
|
|
45
|
-
owner: config.orgName,
|
|
50
|
+
await octokit_js_1.orgOctokit.rest.repos.get({
|
|
51
|
+
owner: env_js_1.config.orgName,
|
|
46
52
|
repo: orgRepoName,
|
|
47
53
|
});
|
|
48
54
|
exists = true;
|
|
49
|
-
spinner.succeed(
|
|
55
|
+
spinner.succeed(chalk_1.default.green(`Repository found in organization.`));
|
|
50
56
|
}
|
|
51
57
|
catch (error) {
|
|
52
58
|
// If it's private and we don't have access, it might return 404
|
|
53
59
|
// but we'll try to proceed anyway and let createRepo handle the collision
|
|
54
|
-
spinner.info(
|
|
60
|
+
spinner.info(chalk_1.default.yellow(`Could not verify existence (may be private or missing).`));
|
|
55
61
|
}
|
|
56
62
|
// 2. Create/Initialize if needed
|
|
57
|
-
if (!exists || !
|
|
58
|
-
spinner.start(`Initializing mirror: ${
|
|
59
|
-
const result = await createRepo(repoName, orgRepoName, owner, shouldRewrite, forcePush, pullChanges, skipPush);
|
|
63
|
+
if (!exists || !fs_1.default.existsSync(localPath)) {
|
|
64
|
+
spinner.start(`Initializing mirror: ${chalk_1.default.blue(owner + '/' + repoName)} → ${chalk_1.default.blue(env_js_1.config.orgName + '/' + orgRepoName)}...`);
|
|
65
|
+
const result = await (0, createRepo_js_1.createRepo)(repoName, orgRepoName, owner, shouldRewrite, forcePush, pullChanges, skipPush);
|
|
60
66
|
if (!result.success && (result.isDiverged || result.requiresManualResolution)) {
|
|
61
|
-
spinner.warn(
|
|
67
|
+
spinner.warn(chalk_1.default.yellow(`Remote changes detected or conflicts found.`));
|
|
62
68
|
return result;
|
|
63
69
|
}
|
|
64
|
-
spinner.succeed(
|
|
70
|
+
spinner.succeed(chalk_1.default.green(result.message));
|
|
65
71
|
// Re-sync if we just created it and skipPush is true
|
|
66
72
|
if (skipPush && result.success) {
|
|
67
|
-
const syncResult = await syncRepo(repoName, orgRepoName, shouldRewrite, forcePush, overwriteSource, skipPush);
|
|
73
|
+
const syncResult = await (0, syncRepo_js_1.syncRepo)(repoName, orgRepoName, shouldRewrite, forcePush, overwriteSource, skipPush);
|
|
68
74
|
// Deduplicate pushes by remote
|
|
69
75
|
const pushMap = new Map();
|
|
70
76
|
const allPushes = [...(result.pendingPushes || []), ...(syncResult.pendingPushes || [])];
|
|
@@ -85,32 +91,32 @@ export async function autoSync(fullRepoName, shouldRewrite = false, forcePush =
|
|
|
85
91
|
}
|
|
86
92
|
}
|
|
87
93
|
else {
|
|
88
|
-
spinner.info(
|
|
94
|
+
spinner.info(chalk_1.default.blue(`Using existing local mirror for ${repoName}.`));
|
|
89
95
|
}
|
|
90
96
|
// 3. Perform the sync
|
|
91
97
|
spinner.start(`Performing two-way synchronization...`);
|
|
92
|
-
const syncResult = await syncRepo(repoName, orgRepoName, shouldRewrite, forcePush, overwriteSource, skipPush);
|
|
98
|
+
const syncResult = await (0, syncRepo_js_1.syncRepo)(repoName, orgRepoName, shouldRewrite, forcePush, overwriteSource, skipPush);
|
|
93
99
|
if (syncResult.success) {
|
|
94
|
-
spinner.succeed(
|
|
100
|
+
spinner.succeed(chalk_1.default.green.bold(`Sync Success!`));
|
|
95
101
|
if (!skipPush) {
|
|
96
|
-
console.log(
|
|
102
|
+
console.log(chalk_1.default.gray(`\nRemotes updated: origin (client) and upstream (org)\n`));
|
|
97
103
|
}
|
|
98
104
|
return { ...syncResult, localPath };
|
|
99
105
|
}
|
|
100
106
|
else if (syncResult.requiresManualResolution) {
|
|
101
|
-
spinner.warn(
|
|
102
|
-
console.log(
|
|
103
|
-
syncResult.conflicts.forEach((f) => console.log(
|
|
104
|
-
console.log(
|
|
107
|
+
spinner.warn(chalk_1.default.yellow.bold(`Action Required: Merge Conflicts!`));
|
|
108
|
+
console.log(chalk_1.default.red(`\nConflicts detected in:`));
|
|
109
|
+
syncResult.conflicts.forEach((f) => console.log(chalk_1.default.red(` • ${f}`)));
|
|
110
|
+
console.log(chalk_1.default.white(`\nPlease resolve manually in: `) + chalk_1.default.cyan(localPath));
|
|
105
111
|
return syncResult;
|
|
106
112
|
}
|
|
107
113
|
else {
|
|
108
|
-
spinner.fail(
|
|
114
|
+
spinner.fail(chalk_1.default.red(`Sync Failed: ${syncResult.message}`));
|
|
109
115
|
return syncResult;
|
|
110
116
|
}
|
|
111
117
|
}
|
|
112
118
|
catch (error) {
|
|
113
|
-
spinner.fail(
|
|
119
|
+
spinner.fail(chalk_1.default.red(`Error: ${error.message}`));
|
|
114
120
|
return {
|
|
115
121
|
success: false,
|
|
116
122
|
message: `Auto-sync failed: ${error.message}`,
|
|
@@ -118,9 +124,9 @@ export async function autoSync(fullRepoName, shouldRewrite = false, forcePush =
|
|
|
118
124
|
};
|
|
119
125
|
}
|
|
120
126
|
finally {
|
|
121
|
-
if (
|
|
127
|
+
if (fs_1.default.existsSync(localPath) && !skipPush) {
|
|
122
128
|
try {
|
|
123
|
-
|
|
129
|
+
fs_1.default.rmSync(localPath, { recursive: true, force: true });
|
|
124
130
|
}
|
|
125
131
|
catch (cleanupError) {
|
|
126
132
|
// Silently ignore cleanup errors or optionally log them
|
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createRepo = createRepo;
|
|
7
|
+
const octokit_js_1 = require("../../config/octokit.js");
|
|
8
|
+
const env_js_1 = require("../../config/env.js");
|
|
9
|
+
const clone_js_1 = require("../../git/clone.js");
|
|
10
|
+
const rewriteAuthor_js_1 = require("../../git/rewriteAuthor.js");
|
|
11
|
+
const simple_git_1 = require("simple-git");
|
|
12
|
+
const sync_js_1 = require("../../git/sync.js");
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const fs_1 = __importDefault(require("fs"));
|
|
15
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
16
|
/**
|
|
11
17
|
* Creates an organization repository and pushes the content of a personal repository to it.
|
|
12
18
|
*/
|
|
13
|
-
|
|
19
|
+
async function createRepo(personalRepoName, orgRepoName, owner, shouldRewrite = false, forcePush = false, pullChanges = false, skipPush = false) {
|
|
14
20
|
// 1. Create the repository in the organization
|
|
15
21
|
let repoCreated = false;
|
|
16
22
|
try {
|
|
17
|
-
await orgOctokit.rest.repos.createInOrg({
|
|
18
|
-
org: config.orgName,
|
|
23
|
+
await octokit_js_1.orgOctokit.rest.repos.createInOrg({
|
|
24
|
+
org: env_js_1.config.orgName,
|
|
19
25
|
name: orgRepoName,
|
|
20
26
|
private: true,
|
|
21
27
|
});
|
|
@@ -31,31 +37,31 @@ export async function createRepo(personalRepoName, orgRepoName, owner, shouldRew
|
|
|
31
37
|
}
|
|
32
38
|
}
|
|
33
39
|
// 2. Clone the personal repo locally
|
|
34
|
-
const tempDir =
|
|
35
|
-
if (
|
|
36
|
-
|
|
40
|
+
const tempDir = path_1.default.join(process.cwd(), 'temp', personalRepoName);
|
|
41
|
+
if (fs_1.default.existsSync(tempDir)) {
|
|
42
|
+
fs_1.default.rmSync(tempDir, { recursive: true, force: true });
|
|
37
43
|
}
|
|
38
|
-
await cloneRepo(owner, personalRepoName, tempDir);
|
|
44
|
+
await (0, clone_js_1.cloneRepo)(owner, personalRepoName, tempDir);
|
|
39
45
|
// 3. Set local author identity for the initial push/clones
|
|
40
46
|
// This is ALWAYS set to ensure correct attribution for any new actions
|
|
41
|
-
const git = simpleGit(tempDir);
|
|
42
|
-
await git.addConfig('user.name', config.authorName);
|
|
43
|
-
await git.addConfig('user.email', config.authorEmail);
|
|
47
|
+
const git = (0, simple_git_1.simpleGit)(tempDir);
|
|
48
|
+
await git.addConfig('user.name', env_js_1.config.authorName);
|
|
49
|
+
await git.addConfig('user.email', env_js_1.config.authorEmail);
|
|
44
50
|
if (shouldRewrite) {
|
|
45
|
-
await rewriteHistory(tempDir, config.authorName, config.authorEmail);
|
|
51
|
+
await (0, rewriteAuthor_js_1.rewriteHistory)(tempDir, env_js_1.config.authorName, env_js_1.config.authorEmail);
|
|
46
52
|
// Force push is REQUIRED if we rewrite history as SHAs change
|
|
47
53
|
forcePush = true;
|
|
48
54
|
}
|
|
49
55
|
// 4. Add org repo as remote and push
|
|
50
|
-
const orgUrl = `https://${config.orgPat}@github.com/${config.orgName}/${orgRepoName}.git`;
|
|
56
|
+
const orgUrl = `https://${env_js_1.config.orgPat}@github.com/${env_js_1.config.orgName}/${orgRepoName}.git`;
|
|
51
57
|
try {
|
|
52
58
|
await git.addRemote('upstream', orgUrl);
|
|
53
59
|
if (pullChanges) {
|
|
54
|
-
console.log(
|
|
55
|
-
await git.fetch('upstream', config.defaultBranch);
|
|
60
|
+
console.log(chalk_1.default.blue(`Pulling and merging changes from ${orgUrl}...`));
|
|
61
|
+
await git.fetch('upstream', env_js_1.config.defaultBranch);
|
|
56
62
|
// Attempt a merge
|
|
57
63
|
try {
|
|
58
|
-
await git.merge([`upstream/${config.defaultBranch}`, '--no-commit', '--no-ff']);
|
|
64
|
+
await git.merge([`upstream/${env_js_1.config.defaultBranch}`, '--no-commit', '--no-ff']);
|
|
59
65
|
const status = await git.status();
|
|
60
66
|
if (status.conflicted.length > 0) {
|
|
61
67
|
return {
|
|
@@ -89,12 +95,12 @@ export async function createRepo(personalRepoName, orgRepoName, owner, shouldRew
|
|
|
89
95
|
const pendingPushes = [];
|
|
90
96
|
pendingPushes.push({
|
|
91
97
|
remote: 'upstream',
|
|
92
|
-
branch: config.defaultBranch,
|
|
98
|
+
branch: env_js_1.config.defaultBranch,
|
|
93
99
|
force: forcePush,
|
|
94
100
|
description: `Organization Repository (upstream)`
|
|
95
101
|
});
|
|
96
102
|
if (!skipPush) {
|
|
97
|
-
await pushToRemote(tempDir, 'upstream', config.defaultBranch, forcePush);
|
|
103
|
+
await (0, sync_js_1.pushToRemote)(tempDir, 'upstream', env_js_1.config.defaultBranch, forcePush);
|
|
98
104
|
}
|
|
99
105
|
return {
|
|
100
106
|
success: true,
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveConflict = resolveConflict;
|
|
4
|
+
async function resolveConflict(fileName, strategy) {
|
|
2
5
|
console.log(`Resolving conflict in ${fileName} using strategy: ${strategy}`);
|
|
3
6
|
// Conflict resolution logic
|
|
4
7
|
}
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.syncRepo = syncRepo;
|
|
7
|
+
const sync_js_1 = require("../../git/sync.js");
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
4
10
|
/**
|
|
5
11
|
* Syncs changes between a personal/client repository and an organization repository.
|
|
6
12
|
*/
|
|
7
|
-
|
|
8
|
-
const localPath =
|
|
9
|
-
if (!
|
|
13
|
+
async function syncRepo(personalRepoName, orgRepoName, shouldRewrite = false, forcePush = false, overwriteSource = false, skipPush = false) {
|
|
14
|
+
const localPath = path_1.default.join(process.cwd(), 'temp', personalRepoName);
|
|
15
|
+
if (!fs_1.default.existsSync(localPath)) {
|
|
10
16
|
return {
|
|
11
17
|
success: false,
|
|
12
18
|
message: `The repository ${personalRepoName} has not been set up yet.`,
|
|
@@ -17,5 +23,5 @@ export async function syncRepo(personalRepoName, orgRepoName, shouldRewrite = fa
|
|
|
17
23
|
};
|
|
18
24
|
}
|
|
19
25
|
// Perform the safe two-way sync
|
|
20
|
-
return await syncBetweenRemotes(localPath, 'origin', 'upstream', shouldRewrite, forcePush, overwriteSource, skipPush);
|
|
26
|
+
return await (0, sync_js_1.syncBetweenRemotes)(localPath, 'origin', 'upstream', shouldRewrite, forcePush, overwriteSource, skipPush);
|
|
21
27
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wipzent/github-sync",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Professional Git history normalization and repository synchronization
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "dist/mcp/server.js",
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "Wipzent Sync: Professional Git history normalization and repository synchronization engine.",
|
|
7
5
|
"bin": {
|
|
8
|
-
"github-sync": "dist/cli/index.js"
|
|
6
|
+
"github-sync": "dist/cli/index.js",
|
|
7
|
+
"wipzent-sync": "dist/cli/index.js"
|
|
9
8
|
},
|
|
10
9
|
"files": [
|
|
11
10
|
"dist",
|
|
@@ -13,15 +12,17 @@
|
|
|
13
12
|
"LICENSE"
|
|
14
13
|
],
|
|
15
14
|
"keywords": [
|
|
16
|
-
"
|
|
17
|
-
"sync",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
15
|
+
"wipzent",
|
|
16
|
+
"wipzent-sync",
|
|
17
|
+
"git-sync",
|
|
18
|
+
"github-sync",
|
|
20
19
|
"history-rewrite",
|
|
20
|
+
"author-normalization",
|
|
21
|
+
"mcp-server",
|
|
21
22
|
"white-label"
|
|
22
23
|
],
|
|
23
24
|
"author": "Wipzent",
|
|
24
|
-
"license": "
|
|
25
|
+
"license": "Proprietary",
|
|
25
26
|
"scripts": {
|
|
26
27
|
"build": "tsc",
|
|
27
28
|
"start": "node dist/mcp/server.js",
|