gitx.do 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -353
- package/dist/do/logger.d.ts +50 -0
- package/dist/do/logger.d.ts.map +1 -0
- package/dist/do/logger.js +122 -0
- package/dist/do/logger.js.map +1 -0
- package/dist/{durable-object → do}/schema.d.ts +3 -3
- package/dist/do/schema.d.ts.map +1 -0
- package/dist/{durable-object → do}/schema.js +4 -3
- package/dist/do/schema.js.map +1 -0
- package/dist/do/types.d.ts +267 -0
- package/dist/do/types.d.ts.map +1 -0
- package/dist/do/types.js +62 -0
- package/dist/do/types.js.map +1 -0
- package/dist/index.d.ts +15 -415
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -483
- package/dist/index.js.map +1 -1
- package/package.json +13 -21
- package/dist/cli/commands/add.d.ts +0 -174
- package/dist/cli/commands/add.d.ts.map +0 -1
- package/dist/cli/commands/add.js +0 -131
- package/dist/cli/commands/add.js.map +0 -1
- package/dist/cli/commands/blame.d.ts +0 -259
- package/dist/cli/commands/blame.d.ts.map +0 -1
- package/dist/cli/commands/blame.js +0 -609
- package/dist/cli/commands/blame.js.map +0 -1
- package/dist/cli/commands/branch.d.ts +0 -249
- package/dist/cli/commands/branch.d.ts.map +0 -1
- package/dist/cli/commands/branch.js +0 -693
- package/dist/cli/commands/branch.js.map +0 -1
- package/dist/cli/commands/commit.d.ts +0 -182
- package/dist/cli/commands/commit.d.ts.map +0 -1
- package/dist/cli/commands/commit.js +0 -437
- package/dist/cli/commands/commit.js.map +0 -1
- package/dist/cli/commands/diff.d.ts +0 -464
- package/dist/cli/commands/diff.d.ts.map +0 -1
- package/dist/cli/commands/diff.js +0 -958
- package/dist/cli/commands/diff.js.map +0 -1
- package/dist/cli/commands/log.d.ts +0 -239
- package/dist/cli/commands/log.d.ts.map +0 -1
- package/dist/cli/commands/log.js +0 -535
- package/dist/cli/commands/log.js.map +0 -1
- package/dist/cli/commands/merge.d.ts +0 -106
- package/dist/cli/commands/merge.d.ts.map +0 -1
- package/dist/cli/commands/merge.js +0 -55
- package/dist/cli/commands/merge.js.map +0 -1
- package/dist/cli/commands/review.d.ts +0 -457
- package/dist/cli/commands/review.d.ts.map +0 -1
- package/dist/cli/commands/review.js +0 -533
- package/dist/cli/commands/review.js.map +0 -1
- package/dist/cli/commands/status.d.ts +0 -269
- package/dist/cli/commands/status.d.ts.map +0 -1
- package/dist/cli/commands/status.js +0 -493
- package/dist/cli/commands/status.js.map +0 -1
- package/dist/cli/commands/web.d.ts +0 -199
- package/dist/cli/commands/web.d.ts.map +0 -1
- package/dist/cli/commands/web.js +0 -696
- package/dist/cli/commands/web.js.map +0 -1
- package/dist/cli/fs-adapter.d.ts +0 -656
- package/dist/cli/fs-adapter.d.ts.map +0 -1
- package/dist/cli/fs-adapter.js +0 -1179
- package/dist/cli/fs-adapter.js.map +0 -1
- package/dist/cli/fsx-cli-adapter.d.ts +0 -359
- package/dist/cli/fsx-cli-adapter.d.ts.map +0 -1
- package/dist/cli/fsx-cli-adapter.js +0 -619
- package/dist/cli/fsx-cli-adapter.js.map +0 -1
- package/dist/cli/index.d.ts +0 -387
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -523
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/ui/components/DiffView.d.ts +0 -7
- package/dist/cli/ui/components/DiffView.d.ts.map +0 -1
- package/dist/cli/ui/components/DiffView.js +0 -11
- package/dist/cli/ui/components/DiffView.js.map +0 -1
- package/dist/cli/ui/components/ErrorDisplay.d.ts +0 -6
- package/dist/cli/ui/components/ErrorDisplay.d.ts.map +0 -1
- package/dist/cli/ui/components/ErrorDisplay.js +0 -11
- package/dist/cli/ui/components/ErrorDisplay.js.map +0 -1
- package/dist/cli/ui/components/FuzzySearch.d.ts +0 -9
- package/dist/cli/ui/components/FuzzySearch.d.ts.map +0 -1
- package/dist/cli/ui/components/FuzzySearch.js +0 -12
- package/dist/cli/ui/components/FuzzySearch.js.map +0 -1
- package/dist/cli/ui/components/LoadingSpinner.d.ts +0 -6
- package/dist/cli/ui/components/LoadingSpinner.d.ts.map +0 -1
- package/dist/cli/ui/components/LoadingSpinner.js +0 -10
- package/dist/cli/ui/components/LoadingSpinner.js.map +0 -1
- package/dist/cli/ui/components/NavigationList.d.ts +0 -9
- package/dist/cli/ui/components/NavigationList.d.ts.map +0 -1
- package/dist/cli/ui/components/NavigationList.js +0 -11
- package/dist/cli/ui/components/NavigationList.js.map +0 -1
- package/dist/cli/ui/components/ScrollableContent.d.ts +0 -8
- package/dist/cli/ui/components/ScrollableContent.d.ts.map +0 -1
- package/dist/cli/ui/components/ScrollableContent.js +0 -11
- package/dist/cli/ui/components/ScrollableContent.js.map +0 -1
- package/dist/cli/ui/components/index.d.ts +0 -7
- package/dist/cli/ui/components/index.d.ts.map +0 -1
- package/dist/cli/ui/components/index.js +0 -9
- package/dist/cli/ui/components/index.js.map +0 -1
- package/dist/cli/ui/terminal-ui.d.ts +0 -52
- package/dist/cli/ui/terminal-ui.d.ts.map +0 -1
- package/dist/cli/ui/terminal-ui.js +0 -121
- package/dist/cli/ui/terminal-ui.js.map +0 -1
- package/dist/do/BashModule.d.ts +0 -871
- package/dist/do/BashModule.d.ts.map +0 -1
- package/dist/do/BashModule.js +0 -1143
- package/dist/do/BashModule.js.map +0 -1
- package/dist/do/FsModule.d.ts +0 -601
- package/dist/do/FsModule.d.ts.map +0 -1
- package/dist/do/FsModule.js +0 -1120
- package/dist/do/FsModule.js.map +0 -1
- package/dist/do/GitModule.d.ts +0 -635
- package/dist/do/GitModule.d.ts.map +0 -1
- package/dist/do/GitModule.js +0 -781
- package/dist/do/GitModule.js.map +0 -1
- package/dist/do/GitRepoDO.d.ts +0 -281
- package/dist/do/GitRepoDO.d.ts.map +0 -1
- package/dist/do/GitRepoDO.js +0 -479
- package/dist/do/GitRepoDO.js.map +0 -1
- package/dist/do/bash-ast.d.ts +0 -246
- package/dist/do/bash-ast.d.ts.map +0 -1
- package/dist/do/bash-ast.js +0 -888
- package/dist/do/bash-ast.js.map +0 -1
- package/dist/do/container-executor.d.ts +0 -491
- package/dist/do/container-executor.d.ts.map +0 -1
- package/dist/do/container-executor.js +0 -730
- package/dist/do/container-executor.js.map +0 -1
- package/dist/do/index.d.ts +0 -53
- package/dist/do/index.d.ts.map +0 -1
- package/dist/do/index.js +0 -91
- package/dist/do/index.js.map +0 -1
- package/dist/do/tiered-storage.d.ts +0 -403
- package/dist/do/tiered-storage.d.ts.map +0 -1
- package/dist/do/tiered-storage.js +0 -689
- package/dist/do/tiered-storage.js.map +0 -1
- package/dist/do/withBash.d.ts +0 -231
- package/dist/do/withBash.d.ts.map +0 -1
- package/dist/do/withBash.js +0 -244
- package/dist/do/withBash.js.map +0 -1
- package/dist/do/withFs.d.ts +0 -237
- package/dist/do/withFs.d.ts.map +0 -1
- package/dist/do/withFs.js +0 -387
- package/dist/do/withFs.js.map +0 -1
- package/dist/do/withGit.d.ts +0 -180
- package/dist/do/withGit.d.ts.map +0 -1
- package/dist/do/withGit.js +0 -271
- package/dist/do/withGit.js.map +0 -1
- package/dist/durable-object/object-store.d.ts +0 -633
- package/dist/durable-object/object-store.d.ts.map +0 -1
- package/dist/durable-object/object-store.js +0 -1161
- package/dist/durable-object/object-store.js.map +0 -1
- package/dist/durable-object/schema.d.ts.map +0 -1
- package/dist/durable-object/schema.js.map +0 -1
- package/dist/durable-object/wal.d.ts +0 -416
- package/dist/durable-object/wal.d.ts.map +0 -1
- package/dist/durable-object/wal.js +0 -445
- package/dist/durable-object/wal.js.map +0 -1
- package/dist/mcp/adapter.d.ts +0 -772
- package/dist/mcp/adapter.d.ts.map +0 -1
- package/dist/mcp/adapter.js +0 -895
- package/dist/mcp/adapter.js.map +0 -1
- package/dist/mcp/sandbox/miniflare-evaluator.d.ts +0 -22
- package/dist/mcp/sandbox/miniflare-evaluator.d.ts.map +0 -1
- package/dist/mcp/sandbox/miniflare-evaluator.js +0 -140
- package/dist/mcp/sandbox/miniflare-evaluator.js.map +0 -1
- package/dist/mcp/sandbox/object-store-proxy.d.ts +0 -32
- package/dist/mcp/sandbox/object-store-proxy.d.ts.map +0 -1
- package/dist/mcp/sandbox/object-store-proxy.js +0 -30
- package/dist/mcp/sandbox/object-store-proxy.js.map +0 -1
- package/dist/mcp/sandbox/template.d.ts +0 -17
- package/dist/mcp/sandbox/template.d.ts.map +0 -1
- package/dist/mcp/sandbox/template.js +0 -71
- package/dist/mcp/sandbox/template.js.map +0 -1
- package/dist/mcp/sandbox.d.ts +0 -764
- package/dist/mcp/sandbox.d.ts.map +0 -1
- package/dist/mcp/sandbox.js +0 -1362
- package/dist/mcp/sandbox.js.map +0 -1
- package/dist/mcp/sdk-adapter.d.ts +0 -835
- package/dist/mcp/sdk-adapter.d.ts.map +0 -1
- package/dist/mcp/sdk-adapter.js +0 -974
- package/dist/mcp/sdk-adapter.js.map +0 -1
- package/dist/mcp/tools/do.d.ts +0 -32
- package/dist/mcp/tools/do.d.ts.map +0 -1
- package/dist/mcp/tools/do.js +0 -115
- package/dist/mcp/tools/do.js.map +0 -1
- package/dist/mcp/tools.d.ts +0 -548
- package/dist/mcp/tools.d.ts.map +0 -1
- package/dist/mcp/tools.js +0 -1934
- package/dist/mcp/tools.js.map +0 -1
- package/dist/ops/blame.d.ts +0 -551
- package/dist/ops/blame.d.ts.map +0 -1
- package/dist/ops/blame.js +0 -1037
- package/dist/ops/blame.js.map +0 -1
- package/dist/ops/branch.d.ts +0 -766
- package/dist/ops/branch.d.ts.map +0 -1
- package/dist/ops/branch.js +0 -950
- package/dist/ops/branch.js.map +0 -1
- package/dist/ops/commit-traversal.d.ts +0 -349
- package/dist/ops/commit-traversal.d.ts.map +0 -1
- package/dist/ops/commit-traversal.js +0 -821
- package/dist/ops/commit-traversal.js.map +0 -1
- package/dist/ops/commit.d.ts +0 -555
- package/dist/ops/commit.d.ts.map +0 -1
- package/dist/ops/commit.js +0 -826
- package/dist/ops/commit.js.map +0 -1
- package/dist/ops/merge-base.d.ts +0 -397
- package/dist/ops/merge-base.d.ts.map +0 -1
- package/dist/ops/merge-base.js +0 -691
- package/dist/ops/merge-base.js.map +0 -1
- package/dist/ops/merge.d.ts +0 -855
- package/dist/ops/merge.d.ts.map +0 -1
- package/dist/ops/merge.js +0 -1551
- package/dist/ops/merge.js.map +0 -1
- package/dist/ops/tag.d.ts +0 -247
- package/dist/ops/tag.d.ts.map +0 -1
- package/dist/ops/tag.js +0 -649
- package/dist/ops/tag.js.map +0 -1
- package/dist/ops/tree-builder.d.ts +0 -178
- package/dist/ops/tree-builder.d.ts.map +0 -1
- package/dist/ops/tree-builder.js +0 -271
- package/dist/ops/tree-builder.js.map +0 -1
- package/dist/ops/tree-diff.d.ts +0 -291
- package/dist/ops/tree-diff.d.ts.map +0 -1
- package/dist/ops/tree-diff.js +0 -705
- package/dist/ops/tree-diff.js.map +0 -1
- package/dist/pack/delta.d.ts +0 -248
- package/dist/pack/delta.d.ts.map +0 -1
- package/dist/pack/delta.js +0 -736
- package/dist/pack/delta.js.map +0 -1
- package/dist/pack/format.d.ts +0 -446
- package/dist/pack/format.d.ts.map +0 -1
- package/dist/pack/format.js +0 -572
- package/dist/pack/format.js.map +0 -1
- package/dist/pack/full-generation.d.ts +0 -612
- package/dist/pack/full-generation.d.ts.map +0 -1
- package/dist/pack/full-generation.js +0 -1378
- package/dist/pack/full-generation.js.map +0 -1
- package/dist/pack/generation.d.ts +0 -441
- package/dist/pack/generation.d.ts.map +0 -1
- package/dist/pack/generation.js +0 -707
- package/dist/pack/generation.js.map +0 -1
- package/dist/pack/index.d.ts +0 -502
- package/dist/pack/index.d.ts.map +0 -1
- package/dist/pack/index.js +0 -833
- package/dist/pack/index.js.map +0 -1
- package/dist/refs/branch.d.ts +0 -668
- package/dist/refs/branch.d.ts.map +0 -1
- package/dist/refs/branch.js +0 -897
- package/dist/refs/branch.js.map +0 -1
- package/dist/refs/storage.d.ts +0 -833
- package/dist/refs/storage.d.ts.map +0 -1
- package/dist/refs/storage.js +0 -1023
- package/dist/refs/storage.js.map +0 -1
- package/dist/refs/tag.d.ts +0 -860
- package/dist/refs/tag.d.ts.map +0 -1
- package/dist/refs/tag.js +0 -996
- package/dist/refs/tag.js.map +0 -1
- package/dist/storage/backend.d.ts +0 -425
- package/dist/storage/backend.d.ts.map +0 -1
- package/dist/storage/backend.js +0 -41
- package/dist/storage/backend.js.map +0 -1
- package/dist/storage/fsx-adapter.d.ts +0 -204
- package/dist/storage/fsx-adapter.d.ts.map +0 -1
- package/dist/storage/fsx-adapter.js +0 -470
- package/dist/storage/fsx-adapter.js.map +0 -1
- package/dist/storage/lru-cache.d.ts +0 -691
- package/dist/storage/lru-cache.d.ts.map +0 -1
- package/dist/storage/lru-cache.js +0 -813
- package/dist/storage/lru-cache.js.map +0 -1
- package/dist/storage/object-index.d.ts +0 -585
- package/dist/storage/object-index.d.ts.map +0 -1
- package/dist/storage/object-index.js +0 -532
- package/dist/storage/object-index.js.map +0 -1
- package/dist/storage/r2-pack.d.ts +0 -1257
- package/dist/storage/r2-pack.d.ts.map +0 -1
- package/dist/storage/r2-pack.js +0 -1770
- package/dist/storage/r2-pack.js.map +0 -1
- package/dist/tiered/cdc-pipeline.d.ts +0 -1888
- package/dist/tiered/cdc-pipeline.d.ts.map +0 -1
- package/dist/tiered/cdc-pipeline.js +0 -1880
- package/dist/tiered/cdc-pipeline.js.map +0 -1
- package/dist/tiered/migration.d.ts +0 -1104
- package/dist/tiered/migration.d.ts.map +0 -1
- package/dist/tiered/migration.js +0 -1214
- package/dist/tiered/migration.js.map +0 -1
- package/dist/tiered/parquet-writer.d.ts +0 -1145
- package/dist/tiered/parquet-writer.d.ts.map +0 -1
- package/dist/tiered/parquet-writer.js +0 -1183
- package/dist/tiered/parquet-writer.js.map +0 -1
- package/dist/tiered/read-path.d.ts +0 -835
- package/dist/tiered/read-path.d.ts.map +0 -1
- package/dist/tiered/read-path.js +0 -487
- package/dist/tiered/read-path.js.map +0 -1
- package/dist/types/capability.d.ts +0 -1385
- package/dist/types/capability.d.ts.map +0 -1
- package/dist/types/capability.js +0 -36
- package/dist/types/capability.js.map +0 -1
- package/dist/types/index.d.ts +0 -13
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -18
- package/dist/types/index.js.map +0 -1
- package/dist/types/objects.d.ts +0 -692
- package/dist/types/objects.d.ts.map +0 -1
- package/dist/types/objects.js +0 -837
- package/dist/types/objects.js.map +0 -1
- package/dist/types/storage.d.ts +0 -603
- package/dist/types/storage.d.ts.map +0 -1
- package/dist/types/storage.js +0 -191
- package/dist/types/storage.js.map +0 -1
- package/dist/types/worker-loader.d.ts +0 -60
- package/dist/types/worker-loader.d.ts.map +0 -1
- package/dist/types/worker-loader.js +0 -62
- package/dist/types/worker-loader.js.map +0 -1
- package/dist/utils/hash.d.ts +0 -197
- package/dist/utils/hash.d.ts.map +0 -1
- package/dist/utils/hash.js +0 -268
- package/dist/utils/hash.js.map +0 -1
- package/dist/utils/sha1.d.ts +0 -290
- package/dist/utils/sha1.d.ts.map +0 -1
- package/dist/utils/sha1.js +0 -582
- package/dist/utils/sha1.js.map +0 -1
- package/dist/wire/capabilities.d.ts +0 -1044
- package/dist/wire/capabilities.d.ts.map +0 -1
- package/dist/wire/capabilities.js +0 -941
- package/dist/wire/capabilities.js.map +0 -1
- package/dist/wire/path-security.d.ts +0 -157
- package/dist/wire/path-security.d.ts.map +0 -1
- package/dist/wire/path-security.js +0 -307
- package/dist/wire/path-security.js.map +0 -1
- package/dist/wire/pkt-line.d.ts +0 -345
- package/dist/wire/pkt-line.d.ts.map +0 -1
- package/dist/wire/pkt-line.js +0 -381
- package/dist/wire/pkt-line.js.map +0 -1
- package/dist/wire/receive-pack.d.ts +0 -1059
- package/dist/wire/receive-pack.d.ts.map +0 -1
- package/dist/wire/receive-pack.js +0 -1414
- package/dist/wire/receive-pack.js.map +0 -1
- package/dist/wire/smart-http.d.ts +0 -799
- package/dist/wire/smart-http.d.ts.map +0 -1
- package/dist/wire/smart-http.js +0 -945
- package/dist/wire/smart-http.js.map +0 -1
- package/dist/wire/upload-pack.d.ts +0 -727
- package/dist/wire/upload-pack.d.ts.map +0 -1
- package/dist/wire/upload-pack.js +0 -1138
- package/dist/wire/upload-pack.js.map +0 -1
package/dist/ops/merge-base.js
DELETED
|
@@ -1,691 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Merge Base Finding Operations
|
|
3
|
-
*
|
|
4
|
-
* Provides functionality for finding merge bases between commits,
|
|
5
|
-
* which is essential for merge operations, rebasing, and understanding
|
|
6
|
-
* branch relationships in the commit graph.
|
|
7
|
-
*
|
|
8
|
-
* ## What is a Merge Base?
|
|
9
|
-
*
|
|
10
|
-
* A merge base is the best common ancestor(s) of two or more commits.
|
|
11
|
-
* The "best" common ancestor is one that is not an ancestor of any
|
|
12
|
-
* other common ancestor (i.e., a maximal common ancestor).
|
|
13
|
-
*
|
|
14
|
-
* ## Features
|
|
15
|
-
*
|
|
16
|
-
* - Find merge base(s) between two commits
|
|
17
|
-
* - Find merge bases for multiple commits (octopus merge)
|
|
18
|
-
* - Fork point detection
|
|
19
|
-
* - Ancestor relationship checking
|
|
20
|
-
* - Independent commit detection
|
|
21
|
-
* - Recursive merge base computation
|
|
22
|
-
*
|
|
23
|
-
* ## Usage Example
|
|
24
|
-
*
|
|
25
|
-
* ```typescript
|
|
26
|
-
* import { findMergeBase, isAncestor } from './ops/merge-base'
|
|
27
|
-
*
|
|
28
|
-
* // Find the merge base between two branches
|
|
29
|
-
* const result = await findMergeBase(provider, [branchA, branchB])
|
|
30
|
-
* if (result.hasCommonHistory) {
|
|
31
|
-
* console.log('Merge base:', result.bases[0])
|
|
32
|
-
* }
|
|
33
|
-
*
|
|
34
|
-
* // Check if one commit is an ancestor of another
|
|
35
|
-
* const isOld = await isAncestor(provider, oldCommit, newCommit)
|
|
36
|
-
* ```
|
|
37
|
-
*
|
|
38
|
-
* @module ops/merge-base
|
|
39
|
-
*/
|
|
40
|
-
// ============================================================================
|
|
41
|
-
// Helper Functions
|
|
42
|
-
// ============================================================================
|
|
43
|
-
/**
|
|
44
|
-
* Gets all ancestors of a commit (including itself).
|
|
45
|
-
*
|
|
46
|
-
* Uses iterative BFS to avoid stack overflow with deep histories.
|
|
47
|
-
* This is the core function used by merge base finding algorithms.
|
|
48
|
-
*
|
|
49
|
-
* @param provider - The commit provider for fetching commits
|
|
50
|
-
* @param sha - The starting commit SHA
|
|
51
|
-
* @returns Set of all ancestor SHAs including the starting commit
|
|
52
|
-
*
|
|
53
|
-
* @internal
|
|
54
|
-
*/
|
|
55
|
-
async function getAncestors(provider, sha) {
|
|
56
|
-
const visited = new Set();
|
|
57
|
-
const queue = [sha];
|
|
58
|
-
while (queue.length > 0) {
|
|
59
|
-
const current = queue.shift();
|
|
60
|
-
if (visited.has(current)) {
|
|
61
|
-
continue;
|
|
62
|
-
}
|
|
63
|
-
const commit = await provider.getCommit(current);
|
|
64
|
-
if (!commit) {
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
visited.add(current);
|
|
68
|
-
for (const parent of commit.parents) {
|
|
69
|
-
if (!visited.has(parent)) {
|
|
70
|
-
queue.push(parent);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return visited;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Finds all common ancestors of two commits.
|
|
78
|
-
*
|
|
79
|
-
* Computes the intersection of ancestor sets for both commits.
|
|
80
|
-
*
|
|
81
|
-
* @param provider - The commit provider for fetching commits
|
|
82
|
-
* @param sha1 - First commit SHA
|
|
83
|
-
* @param sha2 - Second commit SHA
|
|
84
|
-
* @returns Set of all common ancestor SHAs
|
|
85
|
-
*
|
|
86
|
-
* @internal
|
|
87
|
-
*/
|
|
88
|
-
async function findCommonAncestors(provider, sha1, sha2) {
|
|
89
|
-
const ancestors1 = await getAncestors(provider, sha1);
|
|
90
|
-
const ancestors2 = await getAncestors(provider, sha2);
|
|
91
|
-
const common = new Set();
|
|
92
|
-
for (const sha of ancestors1) {
|
|
93
|
-
if (ancestors2.has(sha)) {
|
|
94
|
-
common.add(sha);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return common;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Filters common ancestors to only keep maximal ones.
|
|
101
|
-
*
|
|
102
|
-
* A maximal ancestor is one that is not an ancestor of any other
|
|
103
|
-
* common ancestor. These are the "best" merge bases.
|
|
104
|
-
*
|
|
105
|
-
* @param provider - The commit provider for fetching commits
|
|
106
|
-
* @param commonAncestors - Set of all common ancestors
|
|
107
|
-
* @returns Array of maximal ancestor SHAs (the merge bases)
|
|
108
|
-
*
|
|
109
|
-
* @internal
|
|
110
|
-
*/
|
|
111
|
-
async function filterToMaximalAncestors(provider, commonAncestors) {
|
|
112
|
-
const ancestorsList = Array.from(commonAncestors);
|
|
113
|
-
if (ancestorsList.length === 0) {
|
|
114
|
-
return [];
|
|
115
|
-
}
|
|
116
|
-
if (ancestorsList.length === 1) {
|
|
117
|
-
return ancestorsList;
|
|
118
|
-
}
|
|
119
|
-
// For each ancestor, check if it's an ancestor of any other ancestor
|
|
120
|
-
const isAncestorOfAnother = new Map();
|
|
121
|
-
for (const sha of ancestorsList) {
|
|
122
|
-
isAncestorOfAnother.set(sha, false);
|
|
123
|
-
}
|
|
124
|
-
// Build ancestor sets for each common ancestor
|
|
125
|
-
const ancestorSets = new Map();
|
|
126
|
-
for (const sha of ancestorsList) {
|
|
127
|
-
const ancestors = await getAncestors(provider, sha);
|
|
128
|
-
// Remove the sha itself from its ancestors for comparison
|
|
129
|
-
ancestors.delete(sha);
|
|
130
|
-
ancestorSets.set(sha, ancestors);
|
|
131
|
-
}
|
|
132
|
-
// Check which ones are ancestors of others
|
|
133
|
-
for (const sha of ancestorsList) {
|
|
134
|
-
for (const otherSha of ancestorsList) {
|
|
135
|
-
if (sha !== otherSha) {
|
|
136
|
-
const otherAncestors = ancestorSets.get(otherSha);
|
|
137
|
-
if (otherAncestors.has(sha)) {
|
|
138
|
-
isAncestorOfAnother.set(sha, true);
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// Return only maximal ancestors
|
|
145
|
-
return ancestorsList.filter(sha => !isAncestorOfAnother.get(sha));
|
|
146
|
-
}
|
|
147
|
-
// ============================================================================
|
|
148
|
-
// Core Functions
|
|
149
|
-
// ============================================================================
|
|
150
|
-
/**
|
|
151
|
-
* Find the merge base of two or more commits
|
|
152
|
-
*
|
|
153
|
-
* Given two commits, finds the best common ancestor (merge base).
|
|
154
|
-
* Given multiple commits, finds the merge base of all of them.
|
|
155
|
-
*
|
|
156
|
-
* This is equivalent to `git merge-base`.
|
|
157
|
-
*
|
|
158
|
-
* @param provider - The commit provider for fetching commits
|
|
159
|
-
* @param commits - Two or more commit SHAs
|
|
160
|
-
* @param options - Options for the merge base search
|
|
161
|
-
* @returns The merge base result
|
|
162
|
-
*
|
|
163
|
-
* @example
|
|
164
|
-
* ```ts
|
|
165
|
-
* const result = await findMergeBase(provider, ['abc123', 'def456'])
|
|
166
|
-
* if (result.hasCommonHistory) {
|
|
167
|
-
* console.log('Merge base:', result.bases[0])
|
|
168
|
-
* }
|
|
169
|
-
* ```
|
|
170
|
-
*/
|
|
171
|
-
export async function findMergeBase(provider, commits, options = {}) {
|
|
172
|
-
// Handle edge cases
|
|
173
|
-
if (commits.length === 0) {
|
|
174
|
-
return {
|
|
175
|
-
bases: [],
|
|
176
|
-
isUnique: false,
|
|
177
|
-
hasCommonHistory: false,
|
|
178
|
-
count: 0
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
if (commits.length === 1) {
|
|
182
|
-
const commit = await provider.getCommit(commits[0]);
|
|
183
|
-
if (!commit) {
|
|
184
|
-
return {
|
|
185
|
-
bases: [],
|
|
186
|
-
isUnique: false,
|
|
187
|
-
hasCommonHistory: false,
|
|
188
|
-
count: 0
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
return {
|
|
192
|
-
bases: [commits[0]],
|
|
193
|
-
isUnique: true,
|
|
194
|
-
hasCommonHistory: true,
|
|
195
|
-
count: 1
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
// Handle independent option
|
|
199
|
-
if (options.independent) {
|
|
200
|
-
const independent = await findIndependentCommits(provider, commits);
|
|
201
|
-
return {
|
|
202
|
-
bases: independent,
|
|
203
|
-
isUnique: independent.length === 1,
|
|
204
|
-
hasCommonHistory: independent.length > 0,
|
|
205
|
-
count: independent.length
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
// Handle octopus option
|
|
209
|
-
if (options.octopus || commits.length > 2) {
|
|
210
|
-
const bases = await findOctopusMergeBase(provider, commits);
|
|
211
|
-
return {
|
|
212
|
-
bases,
|
|
213
|
-
isUnique: bases.length === 1,
|
|
214
|
-
hasCommonHistory: bases.length > 0,
|
|
215
|
-
count: bases.length
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
// Handle fork point option
|
|
219
|
-
if (options.forkPoint && commits.length === 2) {
|
|
220
|
-
const result = await findForkPoint(provider, commits[0], commits[1]);
|
|
221
|
-
if (result.found && result.forkPoint) {
|
|
222
|
-
return {
|
|
223
|
-
bases: [result.forkPoint],
|
|
224
|
-
isUnique: true,
|
|
225
|
-
hasCommonHistory: true,
|
|
226
|
-
count: 1
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
// Standard two-commit merge base
|
|
231
|
-
const [sha1, sha2] = commits;
|
|
232
|
-
// Check if either commit doesn't exist
|
|
233
|
-
const commit1 = await provider.getCommit(sha1);
|
|
234
|
-
const commit2 = await provider.getCommit(sha2);
|
|
235
|
-
if (!commit1 || !commit2) {
|
|
236
|
-
return {
|
|
237
|
-
bases: [],
|
|
238
|
-
isUnique: false,
|
|
239
|
-
hasCommonHistory: false,
|
|
240
|
-
count: 0
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
// Find all common ancestors
|
|
244
|
-
const commonAncestors = await findCommonAncestors(provider, sha1, sha2);
|
|
245
|
-
if (commonAncestors.size === 0) {
|
|
246
|
-
return {
|
|
247
|
-
bases: [],
|
|
248
|
-
isUnique: false,
|
|
249
|
-
hasCommonHistory: false,
|
|
250
|
-
count: 0
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
// Filter to maximal ancestors
|
|
254
|
-
const maximalBases = await filterToMaximalAncestors(provider, commonAncestors);
|
|
255
|
-
if (options.all) {
|
|
256
|
-
return {
|
|
257
|
-
bases: maximalBases,
|
|
258
|
-
isUnique: maximalBases.length === 1,
|
|
259
|
-
hasCommonHistory: true,
|
|
260
|
-
count: maximalBases.length
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
// Default: return just one merge base
|
|
264
|
-
return {
|
|
265
|
-
bases: maximalBases.length > 0 ? [maximalBases[0]] : [],
|
|
266
|
-
isUnique: maximalBases.length === 1,
|
|
267
|
-
hasCommonHistory: maximalBases.length > 0,
|
|
268
|
-
count: 1
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Find all merge bases between two commits
|
|
273
|
-
*
|
|
274
|
-
* Unlike findMergeBase with all=true, this specifically finds
|
|
275
|
-
* all maximal common ancestors, which is useful for criss-cross
|
|
276
|
-
* merge situations.
|
|
277
|
-
*
|
|
278
|
-
* This is equivalent to `git merge-base --all`.
|
|
279
|
-
*
|
|
280
|
-
* @param provider - The commit provider for fetching commits
|
|
281
|
-
* @param commit1 - First commit SHA
|
|
282
|
-
* @param commit2 - Second commit SHA
|
|
283
|
-
* @returns Array of all merge base SHAs
|
|
284
|
-
*
|
|
285
|
-
* @example
|
|
286
|
-
* ```ts
|
|
287
|
-
* const bases = await findAllMergeBases(provider, 'abc123', 'def456')
|
|
288
|
-
* if (bases.length > 1) {
|
|
289
|
-
* console.log('Multiple merge bases (criss-cross merge):', bases)
|
|
290
|
-
* }
|
|
291
|
-
* ```
|
|
292
|
-
*/
|
|
293
|
-
export async function findAllMergeBases(provider, commit1, commit2) {
|
|
294
|
-
const result = await findMergeBase(provider, [commit1, commit2], { all: true });
|
|
295
|
-
return result.bases;
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* Find the fork point of a branch relative to another ref
|
|
299
|
-
*
|
|
300
|
-
* Calculates where a branch forked off from another branch,
|
|
301
|
-
* taking into account any rebases that may have occurred.
|
|
302
|
-
* This uses reflog information when available.
|
|
303
|
-
*
|
|
304
|
-
* This is equivalent to `git merge-base --fork-point`.
|
|
305
|
-
*
|
|
306
|
-
* @param provider - The commit provider for fetching commits
|
|
307
|
-
* @param ref - The branch ref to analyze
|
|
308
|
-
* @param baseRef - The base ref to compare against
|
|
309
|
-
* @param reflog - Optional reflog entries for more accurate detection
|
|
310
|
-
* @returns The fork point result
|
|
311
|
-
*
|
|
312
|
-
* @example
|
|
313
|
-
* ```ts
|
|
314
|
-
* const result = await findForkPoint(provider, 'feature-branch', 'main')
|
|
315
|
-
* if (result.found) {
|
|
316
|
-
* console.log('Forked from:', result.forkPoint)
|
|
317
|
-
* }
|
|
318
|
-
* ```
|
|
319
|
-
*/
|
|
320
|
-
export async function findForkPoint(provider, ref, baseRef, reflog) {
|
|
321
|
-
// If reflog is provided, use it for better detection
|
|
322
|
-
if (reflog && reflog.length > 0) {
|
|
323
|
-
// Get ancestors of ref
|
|
324
|
-
const refAncestors = await getAncestors(provider, ref);
|
|
325
|
-
// Check each reflog entry to find the fork point
|
|
326
|
-
for (const entry of reflog) {
|
|
327
|
-
if (refAncestors.has(entry)) {
|
|
328
|
-
// Found a common point in the reflog
|
|
329
|
-
// Calculate commits since fork
|
|
330
|
-
let commitsSinceFork = 0;
|
|
331
|
-
let current = ref;
|
|
332
|
-
while (current !== entry) {
|
|
333
|
-
const commit = await provider.getCommit(current);
|
|
334
|
-
if (!commit || commit.parents.length === 0)
|
|
335
|
-
break;
|
|
336
|
-
commitsSinceFork++;
|
|
337
|
-
current = commit.parents[0];
|
|
338
|
-
}
|
|
339
|
-
return {
|
|
340
|
-
forkPoint: entry,
|
|
341
|
-
ref,
|
|
342
|
-
found: true,
|
|
343
|
-
commitsSinceFork
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
// Standard fork point detection: find merge base
|
|
349
|
-
const result = await findMergeBase(provider, [ref, baseRef]);
|
|
350
|
-
if (!result.hasCommonHistory || result.bases.length === 0) {
|
|
351
|
-
return {
|
|
352
|
-
forkPoint: null,
|
|
353
|
-
ref,
|
|
354
|
-
found: false,
|
|
355
|
-
commitsSinceFork: 0
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
const forkPoint = result.bases[0];
|
|
359
|
-
// Calculate commits since fork
|
|
360
|
-
let commitsSinceFork = 0;
|
|
361
|
-
let current = ref;
|
|
362
|
-
const visited = new Set();
|
|
363
|
-
while (current !== forkPoint && !visited.has(current)) {
|
|
364
|
-
visited.add(current);
|
|
365
|
-
const commit = await provider.getCommit(current);
|
|
366
|
-
if (!commit)
|
|
367
|
-
break;
|
|
368
|
-
if (current === forkPoint)
|
|
369
|
-
break;
|
|
370
|
-
commitsSinceFork++;
|
|
371
|
-
if (commit.parents.length === 0)
|
|
372
|
-
break;
|
|
373
|
-
current = commit.parents[0];
|
|
374
|
-
}
|
|
375
|
-
return {
|
|
376
|
-
forkPoint,
|
|
377
|
-
ref,
|
|
378
|
-
found: true,
|
|
379
|
-
commitsSinceFork
|
|
380
|
-
};
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* Check if one commit is an ancestor of another
|
|
384
|
-
*
|
|
385
|
-
* Returns true if the first commit is reachable from the second
|
|
386
|
-
* commit by following parent links.
|
|
387
|
-
*
|
|
388
|
-
* This is equivalent to `git merge-base --is-ancestor`.
|
|
389
|
-
*
|
|
390
|
-
* @param provider - The commit provider for fetching commits
|
|
391
|
-
* @param potentialAncestor - The commit to check as potential ancestor
|
|
392
|
-
* @param commit - The commit to start walking from
|
|
393
|
-
* @returns True if potentialAncestor is an ancestor of commit
|
|
394
|
-
*
|
|
395
|
-
* @example
|
|
396
|
-
* ```ts
|
|
397
|
-
* if (await isAncestor(provider, 'oldcommit', 'newcommit')) {
|
|
398
|
-
* console.log('oldcommit is an ancestor of newcommit')
|
|
399
|
-
* }
|
|
400
|
-
* ```
|
|
401
|
-
*/
|
|
402
|
-
export async function isAncestor(provider, potentialAncestor, commit) {
|
|
403
|
-
// Same commit is considered its own ancestor
|
|
404
|
-
if (potentialAncestor === commit) {
|
|
405
|
-
return true;
|
|
406
|
-
}
|
|
407
|
-
const ancestors = await getAncestors(provider, commit);
|
|
408
|
-
return ancestors.has(potentialAncestor);
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Checks ancestor relationship and returns additional information.
|
|
412
|
-
*
|
|
413
|
-
* Unlike `isAncestor`, this function also computes the distance
|
|
414
|
-
* (number of commits) between the two commits if they are related.
|
|
415
|
-
*
|
|
416
|
-
* @description
|
|
417
|
-
* Uses BFS to find the shortest path from `commit` to `potentialAncestor`,
|
|
418
|
-
* which gives the minimum distance between them.
|
|
419
|
-
*
|
|
420
|
-
* @param provider - The commit provider for fetching commits
|
|
421
|
-
* @param potentialAncestor - The commit to check as potential ancestor
|
|
422
|
-
* @param commit - The commit to start walking from
|
|
423
|
-
* @returns Detailed ancestor check result with distance information
|
|
424
|
-
*
|
|
425
|
-
* @example
|
|
426
|
-
* ```typescript
|
|
427
|
-
* const result = await checkAncestor(provider, 'abc123', 'def456')
|
|
428
|
-
*
|
|
429
|
-
* if (result.isAncestor) {
|
|
430
|
-
* if (result.distance === 0) {
|
|
431
|
-
* console.log('Same commit')
|
|
432
|
-
* } else {
|
|
433
|
-
* console.log(`abc123 is ${result.distance} commits behind def456`)
|
|
434
|
-
* }
|
|
435
|
-
* } else {
|
|
436
|
-
* console.log('Not an ancestor')
|
|
437
|
-
* }
|
|
438
|
-
* ```
|
|
439
|
-
*/
|
|
440
|
-
export async function checkAncestor(provider, potentialAncestor, commit) {
|
|
441
|
-
// Same commit
|
|
442
|
-
if (potentialAncestor === commit) {
|
|
443
|
-
return {
|
|
444
|
-
isAncestor: true,
|
|
445
|
-
distance: 0
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
// BFS to find the shortest path
|
|
449
|
-
const queue = [{ sha: commit, distance: 0 }];
|
|
450
|
-
const visited = new Set();
|
|
451
|
-
while (queue.length > 0) {
|
|
452
|
-
const { sha, distance } = queue.shift();
|
|
453
|
-
if (visited.has(sha))
|
|
454
|
-
continue;
|
|
455
|
-
visited.add(sha);
|
|
456
|
-
if (sha === potentialAncestor) {
|
|
457
|
-
return {
|
|
458
|
-
isAncestor: true,
|
|
459
|
-
distance
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
const commitObj = await provider.getCommit(sha);
|
|
463
|
-
if (!commitObj)
|
|
464
|
-
continue;
|
|
465
|
-
for (const parent of commitObj.parents) {
|
|
466
|
-
if (!visited.has(parent)) {
|
|
467
|
-
queue.push({ sha: parent, distance: distance + 1 });
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
return {
|
|
472
|
-
isAncestor: false,
|
|
473
|
-
distance: -1
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
// ============================================================================
|
|
477
|
-
// Advanced Functions
|
|
478
|
-
// ============================================================================
|
|
479
|
-
/**
|
|
480
|
-
* Find independent commits from a list
|
|
481
|
-
*
|
|
482
|
-
* Returns the subset of commits that are not reachable from
|
|
483
|
-
* any other commit in the list.
|
|
484
|
-
*
|
|
485
|
-
* This is equivalent to `git merge-base --independent`.
|
|
486
|
-
*
|
|
487
|
-
* @param provider - The commit provider for fetching commits
|
|
488
|
-
* @param commits - List of commit SHAs to analyze
|
|
489
|
-
* @returns Array of independent commit SHAs
|
|
490
|
-
*
|
|
491
|
-
* @example
|
|
492
|
-
* ```ts
|
|
493
|
-
* const independent = await findIndependentCommits(provider, [a, b, c])
|
|
494
|
-
* // Returns commits that are not ancestors of others
|
|
495
|
-
* ```
|
|
496
|
-
*/
|
|
497
|
-
export async function findIndependentCommits(provider, commits) {
|
|
498
|
-
if (commits.length <= 1) {
|
|
499
|
-
return [...commits];
|
|
500
|
-
}
|
|
501
|
-
// Build ancestor sets for each commit
|
|
502
|
-
const ancestorSets = new Map();
|
|
503
|
-
for (const sha of commits) {
|
|
504
|
-
const ancestors = await getAncestors(provider, sha);
|
|
505
|
-
// Remove the commit itself from its ancestor set
|
|
506
|
-
ancestors.delete(sha);
|
|
507
|
-
ancestorSets.set(sha, ancestors);
|
|
508
|
-
}
|
|
509
|
-
// A commit is independent if it's not an ancestor of any other commit in the list
|
|
510
|
-
const independent = [];
|
|
511
|
-
for (const sha of commits) {
|
|
512
|
-
let isAncestorOfAnother = false;
|
|
513
|
-
for (const otherSha of commits) {
|
|
514
|
-
if (sha !== otherSha) {
|
|
515
|
-
const otherAncestors = ancestorSets.get(otherSha);
|
|
516
|
-
if (otherAncestors.has(sha)) {
|
|
517
|
-
isAncestorOfAnother = true;
|
|
518
|
-
break;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
if (!isAncestorOfAnother) {
|
|
523
|
-
independent.push(sha);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
return independent;
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
|
-
* Find the octopus merge base
|
|
530
|
-
*
|
|
531
|
-
* For merging more than two branches, finds a suitable merge base
|
|
532
|
-
* that works for all branches.
|
|
533
|
-
*
|
|
534
|
-
* @param provider - The commit provider for fetching commits
|
|
535
|
-
* @param commits - List of commit SHAs (3 or more)
|
|
536
|
-
* @returns The octopus merge base SHA(s)
|
|
537
|
-
*/
|
|
538
|
-
export async function findOctopusMergeBase(provider, commits) {
|
|
539
|
-
if (commits.length === 0) {
|
|
540
|
-
return [];
|
|
541
|
-
}
|
|
542
|
-
if (commits.length === 1) {
|
|
543
|
-
const commit = await provider.getCommit(commits[0]);
|
|
544
|
-
return commit ? [commits[0]] : [];
|
|
545
|
-
}
|
|
546
|
-
if (commits.length === 2) {
|
|
547
|
-
return findAllMergeBases(provider, commits[0], commits[1]);
|
|
548
|
-
}
|
|
549
|
-
// For 3+ commits, iteratively find the merge base
|
|
550
|
-
// Start with the first two commits
|
|
551
|
-
let currentBases = await findAllMergeBases(provider, commits[0], commits[1]);
|
|
552
|
-
if (currentBases.length === 0) {
|
|
553
|
-
return [];
|
|
554
|
-
}
|
|
555
|
-
// For each additional commit, find the merge base with current bases
|
|
556
|
-
for (let i = 2; i < commits.length; i++) {
|
|
557
|
-
const nextCommit = commits[i];
|
|
558
|
-
const newBases = [];
|
|
559
|
-
for (const base of currentBases) {
|
|
560
|
-
const bases = await findAllMergeBases(provider, base, nextCommit);
|
|
561
|
-
for (const b of bases) {
|
|
562
|
-
if (!newBases.includes(b)) {
|
|
563
|
-
newBases.push(b);
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
if (newBases.length === 0) {
|
|
568
|
-
return [];
|
|
569
|
-
}
|
|
570
|
-
currentBases = newBases;
|
|
571
|
-
}
|
|
572
|
-
return currentBases;
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Compute the three-way merge base for a merge operation
|
|
576
|
-
*
|
|
577
|
-
* Given the current HEAD, merge target, and optionally a common ancestor,
|
|
578
|
-
* returns the appropriate base for a three-way merge.
|
|
579
|
-
*
|
|
580
|
-
* @param provider - The commit provider for fetching commits
|
|
581
|
-
* @param ours - Our commit (HEAD)
|
|
582
|
-
* @param theirs - Their commit (merge target)
|
|
583
|
-
* @returns The merge base for three-way merge
|
|
584
|
-
*/
|
|
585
|
-
export async function computeThreeWayMergeBase(provider, ours, theirs) {
|
|
586
|
-
return findMergeBase(provider, [ours, theirs]);
|
|
587
|
-
}
|
|
588
|
-
/**
|
|
589
|
-
* Checks if commits have any common history.
|
|
590
|
-
*
|
|
591
|
-
* For multiple commits to share common history, every pair of commits
|
|
592
|
-
* must have at least one common ancestor.
|
|
593
|
-
*
|
|
594
|
-
* @description
|
|
595
|
-
* This is useful for detecting if branches can be merged without
|
|
596
|
-
* creating unrelated histories.
|
|
597
|
-
*
|
|
598
|
-
* @param provider - The commit provider for fetching commits
|
|
599
|
-
* @param commits - List of commit SHAs to check
|
|
600
|
-
* @returns True if all commits share common history
|
|
601
|
-
*
|
|
602
|
-
* @example
|
|
603
|
-
* ```typescript
|
|
604
|
-
* const canMerge = await hasCommonHistory(provider, [branchA, branchB, branchC])
|
|
605
|
-
* if (!canMerge) {
|
|
606
|
-
* console.log('Warning: branches have unrelated histories')
|
|
607
|
-
* }
|
|
608
|
-
* ```
|
|
609
|
-
*/
|
|
610
|
-
export async function hasCommonHistory(provider, commits) {
|
|
611
|
-
if (commits.length <= 1) {
|
|
612
|
-
return true;
|
|
613
|
-
}
|
|
614
|
-
// Check pairwise - for common history, all pairs must have a common ancestor
|
|
615
|
-
for (let i = 0; i < commits.length; i++) {
|
|
616
|
-
for (let j = i + 1; j < commits.length; j++) {
|
|
617
|
-
const common = await findCommonAncestors(provider, commits[i], commits[j]);
|
|
618
|
-
if (common.size === 0) {
|
|
619
|
-
return false;
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
return true;
|
|
624
|
-
}
|
|
625
|
-
/**
|
|
626
|
-
* Calculates merge base for a recursive merge.
|
|
627
|
-
*
|
|
628
|
-
* When there are multiple merge bases (criss-cross merge situation),
|
|
629
|
-
* this creates a virtual merge base by recursively merging the merge bases.
|
|
630
|
-
*
|
|
631
|
-
* @description
|
|
632
|
-
* In a criss-cross merge situation, there can be multiple merge bases.
|
|
633
|
-
* The recursive strategy handles this by first finding the merge base
|
|
634
|
-
* of the merge bases, creating a "virtual" common ancestor.
|
|
635
|
-
*
|
|
636
|
-
* This is similar to Git's recursive merge strategy.
|
|
637
|
-
*
|
|
638
|
-
* @param provider - The commit provider for fetching commits
|
|
639
|
-
* @param commit1 - First commit SHA
|
|
640
|
-
* @param commit2 - Second commit SHA
|
|
641
|
-
* @returns The recursive merge base result
|
|
642
|
-
*
|
|
643
|
-
* @example
|
|
644
|
-
* ```typescript
|
|
645
|
-
* // For a criss-cross merge situation:
|
|
646
|
-
* // A---B---C (branch1)
|
|
647
|
-
* // / \ / \
|
|
648
|
-
* // O X (merge)
|
|
649
|
-
* // \ / \ /
|
|
650
|
-
* // D---E---F (branch2)
|
|
651
|
-
*
|
|
652
|
-
* const result = await computeRecursiveMergeBase(provider, 'C', 'F')
|
|
653
|
-
* // Returns a single merge base by recursively merging B and E's common ancestor
|
|
654
|
-
* ```
|
|
655
|
-
*/
|
|
656
|
-
export async function computeRecursiveMergeBase(provider, commit1, commit2) {
|
|
657
|
-
const allBases = await findAllMergeBases(provider, commit1, commit2);
|
|
658
|
-
if (allBases.length === 0) {
|
|
659
|
-
return {
|
|
660
|
-
bases: [],
|
|
661
|
-
isUnique: false,
|
|
662
|
-
hasCommonHistory: false,
|
|
663
|
-
count: 0
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
if (allBases.length === 1) {
|
|
667
|
-
return {
|
|
668
|
-
bases: allBases,
|
|
669
|
-
isUnique: true,
|
|
670
|
-
hasCommonHistory: true,
|
|
671
|
-
count: 1
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
// Multiple merge bases - recursively merge them
|
|
675
|
-
// In a real implementation, this would create virtual merge commits
|
|
676
|
-
// For now, we return the result of recursively finding merge bases of the bases
|
|
677
|
-
let currentBase = allBases[0];
|
|
678
|
-
for (let i = 1; i < allBases.length; i++) {
|
|
679
|
-
const result = await findMergeBase(provider, [currentBase, allBases[i]]);
|
|
680
|
-
if (result.bases.length > 0) {
|
|
681
|
-
currentBase = result.bases[0];
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
return {
|
|
685
|
-
bases: [currentBase],
|
|
686
|
-
isUnique: true,
|
|
687
|
-
hasCommonHistory: true,
|
|
688
|
-
count: 1
|
|
689
|
-
};
|
|
690
|
-
}
|
|
691
|
-
//# sourceMappingURL=merge-base.js.map
|