resulgit 1.0.5 → 1.0.6
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/package.json +1 -1
- package/resulgit.js +88 -79
package/package.json
CHANGED
package/resulgit.js
CHANGED
|
@@ -271,7 +271,7 @@ async function cmdClone(opts, cfg) {
|
|
|
271
271
|
const server = getServer(opts, cfg)
|
|
272
272
|
const token = getToken(opts, cfg)
|
|
273
273
|
const repo = opts.repo
|
|
274
|
-
const branch = opts.branch
|
|
274
|
+
const branch = opts.branch || 'main'
|
|
275
275
|
let dest = opts.dest
|
|
276
276
|
if (!repo || !branch) throw new Error('Missing --repo and --branch')
|
|
277
277
|
const spinner = createSpinner('Initializing clone...', opts.json)
|
|
@@ -540,10 +540,10 @@ async function cmdDiff(opts) {
|
|
|
540
540
|
const snap1 = await fetchSnapshotByCommit(server, meta.repoId, commit1, token)
|
|
541
541
|
const snap2 = await fetchSnapshotByCommit(server, meta.repoId, commit2, token)
|
|
542
542
|
const files = filePath ? [filePath] : Object.keys(new Set([...Object.keys(snap1.files), ...Object.keys(snap2.files)]))
|
|
543
|
-
|
|
543
|
+
|
|
544
544
|
let added = 0, deleted = 0, modified = 0
|
|
545
545
|
const stats = []
|
|
546
|
-
|
|
546
|
+
|
|
547
547
|
for (const p of files) {
|
|
548
548
|
const content1 = snap1.files[p] !== undefined ? String(snap1.files[p]) : null
|
|
549
549
|
const content2 = snap2.files[p] !== undefined ? String(snap2.files[p]) : null
|
|
@@ -561,7 +561,7 @@ async function cmdDiff(opts) {
|
|
|
561
561
|
const diff = Math.abs(lines2.length - lines1.length)
|
|
562
562
|
if (showStat) stats.push({ path: p, added: lines2.length > lines1.length ? diff : 0, deleted: lines1.length > lines2.length ? diff : 0 })
|
|
563
563
|
}
|
|
564
|
-
|
|
564
|
+
|
|
565
565
|
if (!showStat) {
|
|
566
566
|
if (opts.json === 'true') {
|
|
567
567
|
print({ path: p, old: content1, new: content2 }, true)
|
|
@@ -585,7 +585,7 @@ async function cmdDiff(opts) {
|
|
|
585
585
|
}
|
|
586
586
|
}
|
|
587
587
|
}
|
|
588
|
-
|
|
588
|
+
|
|
589
589
|
if (showStat) {
|
|
590
590
|
if (opts.json === 'true') {
|
|
591
591
|
print({ added, deleted, modified, files: stats }, true)
|
|
@@ -607,7 +607,7 @@ async function cmdDiff(opts) {
|
|
|
607
607
|
const parentSnap = parentId ? await fetchSnapshotByCommit(server, meta.repoId, parentId, token) : { files: {}, commitId: '' }
|
|
608
608
|
|
|
609
609
|
const files = filePath ? [filePath] : Object.keys(new Set([...Object.keys(parentSnap.files), ...Object.keys(commitSnap.files)]))
|
|
610
|
-
|
|
610
|
+
|
|
611
611
|
if (showStat) {
|
|
612
612
|
let added = 0, deleted = 0, modified = 0
|
|
613
613
|
const stats = []
|
|
@@ -640,7 +640,7 @@ async function cmdDiff(opts) {
|
|
|
640
640
|
}
|
|
641
641
|
return
|
|
642
642
|
}
|
|
643
|
-
|
|
643
|
+
|
|
644
644
|
for (const p of files) {
|
|
645
645
|
const oldContent = parentSnap.files[p] !== undefined ? String(parentSnap.files[p]) : null
|
|
646
646
|
const newContent = commitSnap.files[p] !== undefined ? String(commitSnap.files[p]) : null
|
|
@@ -726,7 +726,7 @@ async function cmdRm(opts) {
|
|
|
726
726
|
const cfg = loadConfig()
|
|
727
727
|
const server = getServer(opts, cfg) || meta.server
|
|
728
728
|
const token = getToken(opts, cfg) || meta.token
|
|
729
|
-
|
|
729
|
+
|
|
730
730
|
// Handle --cached flag (remove from index but keep file)
|
|
731
731
|
if (opts.cached === 'true') {
|
|
732
732
|
// Mark file for deletion in next commit but don't delete from filesystem
|
|
@@ -736,7 +736,7 @@ async function cmdRm(opts) {
|
|
|
736
736
|
try {
|
|
737
737
|
const s = await fs.promises.readFile(localPath, 'utf8')
|
|
738
738
|
localMeta = JSON.parse(s)
|
|
739
|
-
} catch {}
|
|
739
|
+
} catch { }
|
|
740
740
|
if (!localMeta.removedFiles) localMeta.removedFiles = []
|
|
741
741
|
if (!localMeta.removedFiles.includes(pathArg)) {
|
|
742
742
|
localMeta.removedFiles.push(pathArg)
|
|
@@ -750,7 +750,7 @@ async function cmdRm(opts) {
|
|
|
750
750
|
}
|
|
751
751
|
return
|
|
752
752
|
}
|
|
753
|
-
|
|
753
|
+
|
|
754
754
|
const u = new URL(`/api/repositories/${meta.repoId}/files`, server)
|
|
755
755
|
u.searchParams.set('branch', meta.branch)
|
|
756
756
|
u.searchParams.set('path', pathArg)
|
|
@@ -776,7 +776,7 @@ async function cmdCommit(opts) {
|
|
|
776
776
|
spinnerUpdate(spinner, 'Staging all changes...')
|
|
777
777
|
await cmdAdd({ dir, all: 'true', json: opts.json })
|
|
778
778
|
}
|
|
779
|
-
|
|
779
|
+
|
|
780
780
|
// Handle --amend flag
|
|
781
781
|
if (opts.amend === 'true') {
|
|
782
782
|
spinnerUpdate(spinner, 'Amending last commit...')
|
|
@@ -823,7 +823,7 @@ async function cmdCommit(opts) {
|
|
|
823
823
|
const local = await collectLocal(dir)
|
|
824
824
|
const files = {}
|
|
825
825
|
for (const [p, v] of Object.entries(local)) files[p] = v.content
|
|
826
|
-
|
|
826
|
+
|
|
827
827
|
// Execute pre-commit hook
|
|
828
828
|
spinnerUpdate(spinner, 'Running pre-commit hook...')
|
|
829
829
|
try {
|
|
@@ -836,7 +836,7 @@ async function cmdCommit(opts) {
|
|
|
836
836
|
if (err.message === 'pre-commit hook failed') throw err
|
|
837
837
|
// Hook doesn't exist or other error, continue
|
|
838
838
|
}
|
|
839
|
-
|
|
839
|
+
|
|
840
840
|
localMeta.pendingCommit = { message, files, createdAt: Date.now() }
|
|
841
841
|
// Clear conflicts if they were resolved
|
|
842
842
|
if (localMeta.conflicts) {
|
|
@@ -844,12 +844,12 @@ async function cmdCommit(opts) {
|
|
|
844
844
|
}
|
|
845
845
|
await fs.promises.mkdir(metaDir, { recursive: true })
|
|
846
846
|
await fs.promises.writeFile(localPath, JSON.stringify(localMeta, null, 2))
|
|
847
|
-
|
|
847
|
+
|
|
848
848
|
// Execute post-commit hook
|
|
849
849
|
try {
|
|
850
850
|
await hooks.executeHook(dir, 'post-commit', { message, files: Object.keys(files) })
|
|
851
|
-
} catch {}
|
|
852
|
-
|
|
851
|
+
} catch { }
|
|
852
|
+
|
|
853
853
|
spinnerSuccess(spinner, `Staged changes for commit: "${message}"`)
|
|
854
854
|
print({ pendingCommit: message }, opts.json === 'true')
|
|
855
855
|
} catch (err) {
|
|
@@ -1395,7 +1395,7 @@ async function cmdPush(opts) {
|
|
|
1395
1395
|
if (err.message === 'pre-push hook failed') throw err
|
|
1396
1396
|
// Hook doesn't exist or other error, continue
|
|
1397
1397
|
}
|
|
1398
|
-
|
|
1398
|
+
|
|
1399
1399
|
const body = { message: localMeta.pendingCommit?.message || (opts.message || 'Push'), files: merged, branchName: remoteMeta.branch }
|
|
1400
1400
|
spinnerUpdate(spinner, `Pushing to '${remoteMeta.branch}'...`)
|
|
1401
1401
|
const url = new URL(`/api/repositories/${remoteMeta.repoId}/commits`, server).toString()
|
|
@@ -1404,12 +1404,12 @@ async function cmdPush(opts) {
|
|
|
1404
1404
|
localMeta.baseFiles = merged
|
|
1405
1405
|
localMeta.pendingCommit = null
|
|
1406
1406
|
await fs.promises.writeFile(localPath, JSON.stringify(localMeta, null, 2))
|
|
1407
|
-
|
|
1407
|
+
|
|
1408
1408
|
// Execute post-push hook
|
|
1409
1409
|
try {
|
|
1410
1410
|
await hooks.executeHook(dir, 'post-push', { branch: remoteMeta.branch, commitId: localMeta.baseCommitId })
|
|
1411
|
-
} catch {}
|
|
1412
|
-
|
|
1411
|
+
} catch { }
|
|
1412
|
+
|
|
1413
1413
|
spinnerSuccess(spinner, `Pushed to '${remoteMeta.branch}' (commit: ${(data.id || '').slice(0, 7)})`)
|
|
1414
1414
|
print({ pushed: localMeta.baseCommitId }, opts.json === 'true')
|
|
1415
1415
|
} catch (err) {
|
|
@@ -1758,7 +1758,7 @@ async function cmdBranch(sub, opts) {
|
|
|
1758
1758
|
} catch { }
|
|
1759
1759
|
process.stdout.write(color('Branches:\n', 'bold'))
|
|
1760
1760
|
let list = (data.branches || []).map(b => ({ name: b.name, commitId: b.commitId || '', date: b.lastCommitDate || b.createdAt || '' }))
|
|
1761
|
-
|
|
1761
|
+
|
|
1762
1762
|
// Handle --sort option
|
|
1763
1763
|
if (opts.sort) {
|
|
1764
1764
|
const sortBy = opts.sort.replace(/^-/, '') // Remove leading dash
|
|
@@ -1770,7 +1770,7 @@ async function cmdBranch(sub, opts) {
|
|
|
1770
1770
|
})
|
|
1771
1771
|
}
|
|
1772
1772
|
}
|
|
1773
|
-
|
|
1773
|
+
|
|
1774
1774
|
for (const b of list) {
|
|
1775
1775
|
const isCur = b.name === current
|
|
1776
1776
|
const mark = isCur ? color('*', 'green') : ' '
|
|
@@ -1838,7 +1838,7 @@ async function cmdSwitch(opts) {
|
|
|
1838
1838
|
const cfg = loadConfig()
|
|
1839
1839
|
const server = getServer(opts, cfg) || meta.server
|
|
1840
1840
|
const token = getToken(opts, cfg) || meta.token
|
|
1841
|
-
|
|
1841
|
+
|
|
1842
1842
|
// Handle -c flag (create and switch)
|
|
1843
1843
|
if (create) {
|
|
1844
1844
|
// Check if branch exists
|
|
@@ -1850,7 +1850,7 @@ async function cmdSwitch(opts) {
|
|
|
1850
1850
|
await cmdBranch('create', { dir, name: branch, base: meta.branch, repo: meta.repoId, server, token })
|
|
1851
1851
|
}
|
|
1852
1852
|
}
|
|
1853
|
-
|
|
1853
|
+
|
|
1854
1854
|
await pullToDir(meta.repoId, branch, dir, server, token)
|
|
1855
1855
|
print({ repoId: meta.repoId, branch, dir }, opts.json === 'true')
|
|
1856
1856
|
}
|
|
@@ -2301,8 +2301,10 @@ async function cmdInit(opts) {
|
|
|
2301
2301
|
const cfg = loadConfig()
|
|
2302
2302
|
const server = getServer(opts, cfg)
|
|
2303
2303
|
const token = getToken(opts, cfg)
|
|
2304
|
-
|
|
2305
|
-
const
|
|
2304
|
+
// Repository name must be a non‑empty string; validate format
|
|
2305
|
+
const repo = opts.repo ? validation.validateRepoName(opts.repo) : ''
|
|
2306
|
+
// Branch name defaults to 'main' if not supplied
|
|
2307
|
+
const branch = opts.branch ? opts.branch : 'main'
|
|
2306
2308
|
const metaDir = path.join(dir, '.vcs-next')
|
|
2307
2309
|
const gitDir = path.join(dir, '.git')
|
|
2308
2310
|
await fs.promises.mkdir(metaDir, { recursive: true })
|
|
@@ -2602,38 +2604,38 @@ async function cmdBlame(opts) {
|
|
|
2602
2604
|
const dir = path.resolve(opts.dir || '.')
|
|
2603
2605
|
const filePath = opts.path
|
|
2604
2606
|
if (!filePath) throw new errors.ValidationError('Missing --path', 'path')
|
|
2605
|
-
|
|
2607
|
+
|
|
2606
2608
|
const validPath = validation.validateFilePath(filePath)
|
|
2607
2609
|
const meta = readRemoteMeta(dir)
|
|
2608
2610
|
const cfg = loadConfig()
|
|
2609
2611
|
const server = getServer(opts, cfg) || meta.server
|
|
2610
2612
|
const token = getToken(opts, cfg) || meta.token
|
|
2611
|
-
|
|
2613
|
+
|
|
2612
2614
|
const spinner = createSpinner(`Getting blame for ${validPath}...`, opts.json)
|
|
2613
|
-
|
|
2615
|
+
|
|
2614
2616
|
try {
|
|
2615
2617
|
// Get file content
|
|
2616
2618
|
const local = await collectLocal(dir)
|
|
2617
2619
|
if (!local[validPath]) {
|
|
2618
2620
|
throw new errors.FileSystemError(`File not found: ${validPath}`, validPath, 'read')
|
|
2619
2621
|
}
|
|
2620
|
-
|
|
2622
|
+
|
|
2621
2623
|
// Get commits
|
|
2622
2624
|
const commitsUrl = new URL(`/api/repositories/${meta.repoId}/commits`, server)
|
|
2623
2625
|
commitsUrl.searchParams.set('branch', meta.branch)
|
|
2624
2626
|
const commitsRes = await fetch(commitsUrl.toString(), {
|
|
2625
2627
|
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
2626
2628
|
})
|
|
2627
|
-
|
|
2629
|
+
|
|
2628
2630
|
if (!commitsRes.ok) {
|
|
2629
2631
|
throw new errors.NetworkError('Failed to fetch commits', commitsRes.status, commitsUrl.toString())
|
|
2630
2632
|
}
|
|
2631
|
-
|
|
2633
|
+
|
|
2632
2634
|
const commits = await commitsRes.json()
|
|
2633
2635
|
const blameData = parseBlame(local[validPath].content, commits, validPath)
|
|
2634
|
-
|
|
2636
|
+
|
|
2635
2637
|
spinnerSuccess(spinner, `Blame for ${validPath}`)
|
|
2636
|
-
|
|
2638
|
+
|
|
2637
2639
|
if (opts.json === 'true') {
|
|
2638
2640
|
print(formatBlameJson(blameData), false)
|
|
2639
2641
|
} else {
|
|
@@ -2651,17 +2653,17 @@ async function cmdLog(opts) {
|
|
|
2651
2653
|
const cfg = loadConfig()
|
|
2652
2654
|
const server = getServer(opts, cfg) || meta.server
|
|
2653
2655
|
const token = getToken(opts, cfg) || meta.token
|
|
2654
|
-
|
|
2656
|
+
|
|
2655
2657
|
const spinner = createSpinner('Fetching commit history...', opts.json)
|
|
2656
|
-
|
|
2658
|
+
|
|
2657
2659
|
try {
|
|
2658
2660
|
const url = new URL(`/api/repositories/${meta.repoId}/commits`, server)
|
|
2659
2661
|
if (opts.branch) url.searchParams.set('branch', opts.branch)
|
|
2660
2662
|
else url.searchParams.set('branch', meta.branch)
|
|
2661
|
-
|
|
2663
|
+
|
|
2662
2664
|
const data = await request('GET', url.toString(), null, token)
|
|
2663
2665
|
let commits = Array.isArray(data) ? data : []
|
|
2664
|
-
|
|
2666
|
+
|
|
2665
2667
|
// Filter by file path if provided
|
|
2666
2668
|
const filePath = opts.path
|
|
2667
2669
|
if (filePath) {
|
|
@@ -2674,7 +2676,7 @@ async function cmdLog(opts) {
|
|
|
2674
2676
|
}
|
|
2675
2677
|
commits = filteredCommits
|
|
2676
2678
|
}
|
|
2677
|
-
|
|
2679
|
+
|
|
2678
2680
|
// Filter by content pattern (-G flag)
|
|
2679
2681
|
const pattern = opts.G || opts.pattern
|
|
2680
2682
|
if (pattern) {
|
|
@@ -2684,7 +2686,7 @@ async function cmdLog(opts) {
|
|
|
2684
2686
|
const commitSnap = await fetchSnapshotByCommit(server, meta.repoId, commit.id || commit._id, token)
|
|
2685
2687
|
const parentId = (Array.isArray(commit.parents) && commit.parents[0]) || ''
|
|
2686
2688
|
const parentSnap = parentId ? await fetchSnapshotByCommit(server, meta.repoId, parentId, token) : { files: {} }
|
|
2687
|
-
|
|
2689
|
+
|
|
2688
2690
|
// Check if pattern matches in any file changed in this commit
|
|
2689
2691
|
const allPaths = new Set([...Object.keys(parentSnap.files), ...Object.keys(commitSnap.files)])
|
|
2690
2692
|
let matches = false
|
|
@@ -2702,9 +2704,9 @@ async function cmdLog(opts) {
|
|
|
2702
2704
|
}
|
|
2703
2705
|
commits = filteredCommits
|
|
2704
2706
|
}
|
|
2705
|
-
|
|
2707
|
+
|
|
2706
2708
|
spinnerSuccess(spinner, `Found ${commits.length} commits`)
|
|
2707
|
-
|
|
2709
|
+
|
|
2708
2710
|
if (opts.json === 'true') {
|
|
2709
2711
|
print(commits, true)
|
|
2710
2712
|
} else if (opts.oneline === 'true') {
|
|
@@ -2733,7 +2735,7 @@ async function cmdLog(opts) {
|
|
|
2733
2735
|
|
|
2734
2736
|
async function cmdHook(sub, opts) {
|
|
2735
2737
|
const dir = path.resolve(opts.dir || '.')
|
|
2736
|
-
|
|
2738
|
+
|
|
2737
2739
|
if (sub === 'list') {
|
|
2738
2740
|
const hooksList = await hooks.listHooks(dir)
|
|
2739
2741
|
if (opts.json === 'true') {
|
|
@@ -2751,18 +2753,18 @@ async function cmdHook(sub, opts) {
|
|
|
2751
2753
|
}
|
|
2752
2754
|
return
|
|
2753
2755
|
}
|
|
2754
|
-
|
|
2756
|
+
|
|
2755
2757
|
if (sub === 'install') {
|
|
2756
2758
|
const hookName = opts.name
|
|
2757
2759
|
if (!hookName) throw new Error('Missing --name')
|
|
2758
|
-
|
|
2760
|
+
|
|
2759
2761
|
let script = opts.script
|
|
2760
2762
|
if (!script && opts.sample === 'true') {
|
|
2761
2763
|
script = hooks.SAMPLE_HOOKS[hookName]
|
|
2762
2764
|
if (!script) throw new Error(`No sample available for ${hookName}`)
|
|
2763
2765
|
}
|
|
2764
2766
|
if (!script) throw new Error('Missing --script or use --sample')
|
|
2765
|
-
|
|
2767
|
+
|
|
2766
2768
|
const result = await hooks.installHook(dir, hookName, script)
|
|
2767
2769
|
print(result, opts.json === 'true')
|
|
2768
2770
|
if (opts.json !== 'true') {
|
|
@@ -2770,20 +2772,20 @@ async function cmdHook(sub, opts) {
|
|
|
2770
2772
|
}
|
|
2771
2773
|
return
|
|
2772
2774
|
}
|
|
2773
|
-
|
|
2775
|
+
|
|
2774
2776
|
if (sub === 'remove') {
|
|
2775
2777
|
const hookName = opts.name
|
|
2776
2778
|
if (!hookName) throw new Error('Missing --name')
|
|
2777
|
-
|
|
2779
|
+
|
|
2778
2780
|
const result = await hooks.removeHook(dir, hookName)
|
|
2779
2781
|
print(result, opts.json === 'true')
|
|
2780
2782
|
return
|
|
2781
2783
|
}
|
|
2782
|
-
|
|
2784
|
+
|
|
2783
2785
|
if (sub === 'show') {
|
|
2784
2786
|
const hookName = opts.name
|
|
2785
2787
|
if (!hookName) throw new Error('Missing --name')
|
|
2786
|
-
|
|
2788
|
+
|
|
2787
2789
|
const result = await hooks.readHook(dir, hookName)
|
|
2788
2790
|
if (result.content) {
|
|
2789
2791
|
process.stdout.write(result.content + '\n')
|
|
@@ -2792,7 +2794,7 @@ async function cmdHook(sub, opts) {
|
|
|
2792
2794
|
}
|
|
2793
2795
|
return
|
|
2794
2796
|
}
|
|
2795
|
-
|
|
2797
|
+
|
|
2796
2798
|
throw new Error('Unknown hook subcommand. Use: list, install, remove, show')
|
|
2797
2799
|
}
|
|
2798
2800
|
|
|
@@ -2800,13 +2802,13 @@ async function cmdGrep(opts) {
|
|
|
2800
2802
|
const dir = path.resolve(opts.dir || '.')
|
|
2801
2803
|
const pattern = opts.pattern || opts.p || ''
|
|
2802
2804
|
if (!pattern) throw new Error('Missing --pattern or -p')
|
|
2803
|
-
|
|
2805
|
+
|
|
2804
2806
|
const meta = readRemoteMeta(dir)
|
|
2805
2807
|
const local = await collectLocal(dir)
|
|
2806
2808
|
const results = []
|
|
2807
|
-
|
|
2809
|
+
|
|
2808
2810
|
const regex = new RegExp(pattern, opts.ignoreCase === 'true' ? 'i' : '')
|
|
2809
|
-
|
|
2811
|
+
|
|
2810
2812
|
for (const [filePath, fileData] of Object.entries(local)) {
|
|
2811
2813
|
const lines = fileData.content.split(/\r?\n/)
|
|
2812
2814
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -2819,7 +2821,7 @@ async function cmdGrep(opts) {
|
|
|
2819
2821
|
}
|
|
2820
2822
|
}
|
|
2821
2823
|
}
|
|
2822
|
-
|
|
2824
|
+
|
|
2823
2825
|
if (opts.json === 'true') {
|
|
2824
2826
|
print(results, true)
|
|
2825
2827
|
} else {
|
|
@@ -2836,10 +2838,10 @@ async function cmdLsFiles(opts) {
|
|
|
2836
2838
|
const cfg = loadConfig()
|
|
2837
2839
|
const server = getServer(opts, cfg) || meta.server
|
|
2838
2840
|
const token = getToken(opts, cfg) || meta.token
|
|
2839
|
-
|
|
2841
|
+
|
|
2840
2842
|
const remote = await fetchRemoteFilesMap(server, meta.repoId, meta.branch, token)
|
|
2841
2843
|
const files = Object.keys(remote.map)
|
|
2842
|
-
|
|
2844
|
+
|
|
2843
2845
|
if (opts.json === 'true') {
|
|
2844
2846
|
print(files.map(f => ({ path: f })), true)
|
|
2845
2847
|
} else {
|
|
@@ -2853,13 +2855,13 @@ async function cmdReflog(opts) {
|
|
|
2853
2855
|
const dir = path.resolve(opts.dir || '.')
|
|
2854
2856
|
const metaDir = path.join(dir, '.vcs-next')
|
|
2855
2857
|
const reflogPath = path.join(metaDir, 'reflog.json')
|
|
2856
|
-
|
|
2858
|
+
|
|
2857
2859
|
let reflog = []
|
|
2858
2860
|
try {
|
|
2859
2861
|
const content = await fs.promises.readFile(reflogPath, 'utf8')
|
|
2860
2862
|
reflog = JSON.parse(content)
|
|
2861
|
-
} catch {}
|
|
2862
|
-
|
|
2863
|
+
} catch { }
|
|
2864
|
+
|
|
2863
2865
|
if (opts.json === 'true') {
|
|
2864
2866
|
print(reflog, true)
|
|
2865
2867
|
} else {
|
|
@@ -2878,14 +2880,14 @@ async function cmdCatFile(opts) {
|
|
|
2878
2880
|
const dir = path.resolve(opts.dir || '.')
|
|
2879
2881
|
const type = opts.type || ''
|
|
2880
2882
|
const object = opts.object || ''
|
|
2881
|
-
|
|
2883
|
+
|
|
2882
2884
|
if (!type || !object) throw new Error('Missing --type and --object')
|
|
2883
|
-
|
|
2885
|
+
|
|
2884
2886
|
const meta = readRemoteMeta(dir)
|
|
2885
2887
|
const cfg = loadConfig()
|
|
2886
2888
|
const server = getServer(opts, cfg) || meta.server
|
|
2887
2889
|
const token = getToken(opts, cfg) || meta.token
|
|
2888
|
-
|
|
2890
|
+
|
|
2889
2891
|
if (type === 'blob') {
|
|
2890
2892
|
const snap = await fetchSnapshotByCommit(server, meta.repoId, object, token)
|
|
2891
2893
|
const filePath = opts.path || ''
|
|
@@ -2912,12 +2914,12 @@ async function cmdCatFile(opts) {
|
|
|
2912
2914
|
async function cmdRevParse(opts) {
|
|
2913
2915
|
const dir = path.resolve(opts.dir || '.')
|
|
2914
2916
|
const rev = opts.rev || 'HEAD'
|
|
2915
|
-
|
|
2917
|
+
|
|
2916
2918
|
const meta = readRemoteMeta(dir)
|
|
2917
2919
|
const cfg = loadConfig()
|
|
2918
2920
|
const server = getServer(opts, cfg) || meta.server
|
|
2919
2921
|
const token = getToken(opts, cfg) || meta.token
|
|
2920
|
-
|
|
2922
|
+
|
|
2921
2923
|
if (rev === 'HEAD') {
|
|
2922
2924
|
const info = await request('GET', new URL(`/api/repositories/${meta.repoId}/branches`, server).toString(), null, token)
|
|
2923
2925
|
const found = (info.branches || []).find(b => b.name === meta.branch)
|
|
@@ -2938,20 +2940,20 @@ async function cmdRevParse(opts) {
|
|
|
2938
2940
|
async function cmdDescribe(opts) {
|
|
2939
2941
|
const dir = path.resolve(opts.dir || '.')
|
|
2940
2942
|
const commitId = opts.commit || 'HEAD'
|
|
2941
|
-
|
|
2943
|
+
|
|
2942
2944
|
const meta = readRemoteMeta(dir)
|
|
2943
2945
|
const cfg = loadConfig()
|
|
2944
2946
|
const server = getServer(opts, cfg) || meta.server
|
|
2945
2947
|
const token = getToken(opts, cfg) || meta.token
|
|
2946
|
-
|
|
2948
|
+
|
|
2947
2949
|
// Get tags
|
|
2948
2950
|
const tagsUrl = new URL(`/api/repositories/${meta.repoId}/tags`, server)
|
|
2949
2951
|
const tags = await request('GET', tagsUrl.toString(), null, token)
|
|
2950
2952
|
const tagsList = Array.isArray(tags) ? tags : []
|
|
2951
|
-
|
|
2953
|
+
|
|
2952
2954
|
// Find nearest tag (simplified - just find any tag)
|
|
2953
2955
|
const nearestTag = tagsList[0]
|
|
2954
|
-
|
|
2956
|
+
|
|
2955
2957
|
if (nearestTag) {
|
|
2956
2958
|
const desc = `${nearestTag.name}-0-g${commitId.slice(0, 7)}`
|
|
2957
2959
|
print(opts.json === 'true' ? { tag: nearestTag.name, commitId, describe: desc } : desc, opts.json === 'true')
|
|
@@ -2966,16 +2968,16 @@ async function cmdShortlog(opts) {
|
|
|
2966
2968
|
const cfg = loadConfig()
|
|
2967
2969
|
const server = getServer(opts, cfg) || meta.server
|
|
2968
2970
|
const token = getToken(opts, cfg) || meta.token
|
|
2969
|
-
|
|
2971
|
+
|
|
2970
2972
|
const url = new URL(`/api/repositories/${meta.repoId}/commits`, server)
|
|
2971
2973
|
if (opts.branch) url.searchParams.set('branch', opts.branch)
|
|
2972
2974
|
else url.searchParams.set('branch', meta.branch)
|
|
2973
|
-
|
|
2975
|
+
|
|
2974
2976
|
const commits = await request('GET', url.toString(), null, token)
|
|
2975
2977
|
const commitsList = Array.isArray(commits) ? commits : []
|
|
2976
|
-
|
|
2978
|
+
|
|
2977
2979
|
const stats = generateCommitStats(commitsList)
|
|
2978
|
-
|
|
2980
|
+
|
|
2979
2981
|
if (opts.json === 'true') {
|
|
2980
2982
|
print(stats, true)
|
|
2981
2983
|
} else {
|
|
@@ -3044,8 +3046,8 @@ function help() {
|
|
|
3044
3046
|
' >>>>>>> incoming (incoming changes)',
|
|
3045
3047
|
' Resolve conflicts manually, then commit and push. Push is blocked until conflicts are resolved.',
|
|
3046
3048
|
' pr list|create|merge [--dir <path>] [--title <t>] [--id <id>] [--source <branch>] [--target <branch>]',
|
|
3047
|
-
' clone <url> [--dest <dir>] | --repo <
|
|
3048
|
-
' init [--dir <path>] [--repo <
|
|
3049
|
+
' clone <url> [--dest <dir>] | --repo <name> --branch <name> [--dest <dir>] [--server <url>] [--token <token>]',
|
|
3050
|
+
' init [--dir <path>] [--repo <name>] [--server <url>] [--branch <name>] [--token <tok>]',
|
|
3049
3051
|
' remote show|set-url|set-token [--dir <path>] [--server <url>] [--token <tok>]',
|
|
3050
3052
|
' config list|get|set [--key <k>] [--value <v>]',
|
|
3051
3053
|
' clean [--dir <path>] [--force]',
|
|
@@ -3078,13 +3080,20 @@ async function main() {
|
|
|
3078
3080
|
return
|
|
3079
3081
|
}
|
|
3080
3082
|
if (cmd[0] === 'clone') {
|
|
3081
|
-
|
|
3083
|
+
const arg = cmd[1];
|
|
3084
|
+
if (arg && !arg.startsWith('--')) {
|
|
3085
|
+
if (arg.includes('://')) {
|
|
3086
|
+
opts.url = arg;
|
|
3087
|
+
} else {
|
|
3088
|
+
opts.repo = arg;
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3082
3091
|
if (opts.url) {
|
|
3083
|
-
await cmdCloneFromUrl(opts, cfg)
|
|
3092
|
+
await cmdCloneFromUrl(opts, cfg);
|
|
3084
3093
|
} else {
|
|
3085
|
-
await cmdClone(opts, cfg)
|
|
3094
|
+
await cmdClone(opts, cfg);
|
|
3086
3095
|
}
|
|
3087
|
-
return
|
|
3096
|
+
return;
|
|
3088
3097
|
}
|
|
3089
3098
|
if (cmd[0] === 'status') {
|
|
3090
3099
|
await cmdStatus(opts)
|