@git-stunts/git-warp 10.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/NOTICE +16 -0
- package/README.md +480 -0
- package/SECURITY.md +30 -0
- package/bin/git-warp +24 -0
- package/bin/warp-graph.js +1574 -0
- package/index.d.ts +2366 -0
- package/index.js +180 -0
- package/package.json +129 -0
- package/scripts/install-git-warp.sh +258 -0
- package/scripts/uninstall-git-warp.sh +139 -0
- package/src/domain/WarpGraph.js +3157 -0
- package/src/domain/crdt/Dot.js +160 -0
- package/src/domain/crdt/LWW.js +154 -0
- package/src/domain/crdt/ORSet.js +371 -0
- package/src/domain/crdt/VersionVector.js +222 -0
- package/src/domain/entities/GraphNode.js +60 -0
- package/src/domain/errors/EmptyMessageError.js +47 -0
- package/src/domain/errors/ForkError.js +30 -0
- package/src/domain/errors/IndexError.js +23 -0
- package/src/domain/errors/OperationAbortedError.js +22 -0
- package/src/domain/errors/QueryError.js +39 -0
- package/src/domain/errors/SchemaUnsupportedError.js +17 -0
- package/src/domain/errors/ShardCorruptionError.js +56 -0
- package/src/domain/errors/ShardLoadError.js +57 -0
- package/src/domain/errors/ShardValidationError.js +61 -0
- package/src/domain/errors/StorageError.js +57 -0
- package/src/domain/errors/SyncError.js +30 -0
- package/src/domain/errors/TraversalError.js +23 -0
- package/src/domain/errors/WarpError.js +31 -0
- package/src/domain/errors/WormholeError.js +28 -0
- package/src/domain/errors/WriterError.js +39 -0
- package/src/domain/errors/index.js +21 -0
- package/src/domain/services/AnchorMessageCodec.js +99 -0
- package/src/domain/services/BitmapIndexBuilder.js +225 -0
- package/src/domain/services/BitmapIndexReader.js +435 -0
- package/src/domain/services/BoundaryTransitionRecord.js +463 -0
- package/src/domain/services/CheckpointMessageCodec.js +147 -0
- package/src/domain/services/CheckpointSerializerV5.js +281 -0
- package/src/domain/services/CheckpointService.js +384 -0
- package/src/domain/services/CommitDagTraversalService.js +156 -0
- package/src/domain/services/DagPathFinding.js +712 -0
- package/src/domain/services/DagTopology.js +239 -0
- package/src/domain/services/DagTraversal.js +245 -0
- package/src/domain/services/Frontier.js +108 -0
- package/src/domain/services/GCMetrics.js +101 -0
- package/src/domain/services/GCPolicy.js +122 -0
- package/src/domain/services/GitLogParser.js +205 -0
- package/src/domain/services/HealthCheckService.js +246 -0
- package/src/domain/services/HookInstaller.js +326 -0
- package/src/domain/services/HttpSyncServer.js +262 -0
- package/src/domain/services/IndexRebuildService.js +426 -0
- package/src/domain/services/IndexStalenessChecker.js +103 -0
- package/src/domain/services/JoinReducer.js +582 -0
- package/src/domain/services/KeyCodec.js +113 -0
- package/src/domain/services/LegacyAnchorDetector.js +67 -0
- package/src/domain/services/LogicalTraversal.js +351 -0
- package/src/domain/services/MessageCodecInternal.js +132 -0
- package/src/domain/services/MessageSchemaDetector.js +145 -0
- package/src/domain/services/MigrationService.js +55 -0
- package/src/domain/services/ObserverView.js +265 -0
- package/src/domain/services/PatchBuilderV2.js +669 -0
- package/src/domain/services/PatchMessageCodec.js +140 -0
- package/src/domain/services/ProvenanceIndex.js +337 -0
- package/src/domain/services/ProvenancePayload.js +242 -0
- package/src/domain/services/QueryBuilder.js +835 -0
- package/src/domain/services/StateDiff.js +300 -0
- package/src/domain/services/StateSerializerV5.js +156 -0
- package/src/domain/services/StreamingBitmapIndexBuilder.js +709 -0
- package/src/domain/services/SyncProtocol.js +593 -0
- package/src/domain/services/TemporalQuery.js +201 -0
- package/src/domain/services/TranslationCost.js +221 -0
- package/src/domain/services/TraversalService.js +8 -0
- package/src/domain/services/WarpMessageCodec.js +29 -0
- package/src/domain/services/WarpStateIndexBuilder.js +127 -0
- package/src/domain/services/WormholeService.js +353 -0
- package/src/domain/types/TickReceipt.js +285 -0
- package/src/domain/types/WarpTypes.js +209 -0
- package/src/domain/types/WarpTypesV2.js +200 -0
- package/src/domain/utils/CachedValue.js +140 -0
- package/src/domain/utils/EventId.js +89 -0
- package/src/domain/utils/LRUCache.js +112 -0
- package/src/domain/utils/MinHeap.js +114 -0
- package/src/domain/utils/RefLayout.js +280 -0
- package/src/domain/utils/WriterId.js +205 -0
- package/src/domain/utils/cancellation.js +33 -0
- package/src/domain/utils/canonicalStringify.js +42 -0
- package/src/domain/utils/defaultClock.js +20 -0
- package/src/domain/utils/defaultCodec.js +51 -0
- package/src/domain/utils/nullLogger.js +21 -0
- package/src/domain/utils/roaring.js +181 -0
- package/src/domain/utils/shardVersion.js +9 -0
- package/src/domain/warp/PatchSession.js +217 -0
- package/src/domain/warp/Writer.js +181 -0
- package/src/hooks/post-merge.sh +60 -0
- package/src/infrastructure/adapters/BunHttpAdapter.js +225 -0
- package/src/infrastructure/adapters/ClockAdapter.js +57 -0
- package/src/infrastructure/adapters/ConsoleLogger.js +150 -0
- package/src/infrastructure/adapters/DenoHttpAdapter.js +230 -0
- package/src/infrastructure/adapters/GitGraphAdapter.js +787 -0
- package/src/infrastructure/adapters/GlobalClockAdapter.js +5 -0
- package/src/infrastructure/adapters/NoOpLogger.js +62 -0
- package/src/infrastructure/adapters/NodeCryptoAdapter.js +32 -0
- package/src/infrastructure/adapters/NodeHttpAdapter.js +98 -0
- package/src/infrastructure/adapters/PerformanceClockAdapter.js +5 -0
- package/src/infrastructure/adapters/WebCryptoAdapter.js +121 -0
- package/src/infrastructure/codecs/CborCodec.js +384 -0
- package/src/ports/BlobPort.js +30 -0
- package/src/ports/ClockPort.js +25 -0
- package/src/ports/CodecPort.js +25 -0
- package/src/ports/CommitPort.js +114 -0
- package/src/ports/ConfigPort.js +31 -0
- package/src/ports/CryptoPort.js +38 -0
- package/src/ports/GraphPersistencePort.js +57 -0
- package/src/ports/HttpServerPort.js +25 -0
- package/src/ports/IndexStoragePort.js +39 -0
- package/src/ports/LoggerPort.js +68 -0
- package/src/ports/RefPort.js +51 -0
- package/src/ports/TreePort.js +51 -0
- package/src/visualization/index.js +26 -0
- package/src/visualization/layouts/converters.js +75 -0
- package/src/visualization/layouts/elkAdapter.js +86 -0
- package/src/visualization/layouts/elkLayout.js +95 -0
- package/src/visualization/layouts/index.js +29 -0
- package/src/visualization/renderers/ascii/box.js +16 -0
- package/src/visualization/renderers/ascii/check.js +271 -0
- package/src/visualization/renderers/ascii/colors.js +13 -0
- package/src/visualization/renderers/ascii/formatters.js +73 -0
- package/src/visualization/renderers/ascii/graph.js +344 -0
- package/src/visualization/renderers/ascii/history.js +335 -0
- package/src/visualization/renderers/ascii/index.js +14 -0
- package/src/visualization/renderers/ascii/info.js +245 -0
- package/src/visualization/renderers/ascii/materialize.js +255 -0
- package/src/visualization/renderers/ascii/path.js +240 -0
- package/src/visualization/renderers/ascii/progress.js +32 -0
- package/src/visualization/renderers/ascii/symbols.js +33 -0
- package/src/visualization/renderers/ascii/table.js +19 -0
- package/src/visualization/renderers/browser/index.js +1 -0
- package/src/visualization/renderers/svg/index.js +159 -0
- package/src/visualization/utils/ansi.js +14 -0
- package/src/visualization/utils/time.js +40 -0
- package/src/visualization/utils/truncate.js +40 -0
- package/src/visualization/utils/unicode.js +52 -0
package/index.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Empty Graph - A graph database substrate using Git commits pointing to the empty tree.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import GitGraphAdapter from './src/infrastructure/adapters/GitGraphAdapter.js';
|
|
6
|
+
import GraphNode from './src/domain/entities/GraphNode.js';
|
|
7
|
+
import BitmapIndexBuilder from './src/domain/services/BitmapIndexBuilder.js';
|
|
8
|
+
import BitmapIndexReader from './src/domain/services/BitmapIndexReader.js';
|
|
9
|
+
import IndexRebuildService from './src/domain/services/IndexRebuildService.js';
|
|
10
|
+
import HealthCheckService, { HealthStatus } from './src/domain/services/HealthCheckService.js';
|
|
11
|
+
import CommitDagTraversalService from './src/domain/services/CommitDagTraversalService.js';
|
|
12
|
+
import GraphPersistencePort from './src/ports/GraphPersistencePort.js';
|
|
13
|
+
import IndexStoragePort from './src/ports/IndexStoragePort.js';
|
|
14
|
+
import LoggerPort from './src/ports/LoggerPort.js';
|
|
15
|
+
import ClockPort from './src/ports/ClockPort.js';
|
|
16
|
+
import NoOpLogger from './src/infrastructure/adapters/NoOpLogger.js';
|
|
17
|
+
import ConsoleLogger, { LogLevel } from './src/infrastructure/adapters/ConsoleLogger.js';
|
|
18
|
+
import ClockAdapter from './src/infrastructure/adapters/ClockAdapter.js';
|
|
19
|
+
import PerformanceClockAdapter from './src/infrastructure/adapters/PerformanceClockAdapter.js';
|
|
20
|
+
import GlobalClockAdapter from './src/infrastructure/adapters/GlobalClockAdapter.js';
|
|
21
|
+
import {
|
|
22
|
+
ForkError,
|
|
23
|
+
IndexError,
|
|
24
|
+
QueryError,
|
|
25
|
+
SchemaUnsupportedError,
|
|
26
|
+
ShardLoadError,
|
|
27
|
+
ShardCorruptionError,
|
|
28
|
+
ShardValidationError,
|
|
29
|
+
StorageError,
|
|
30
|
+
TraversalError,
|
|
31
|
+
OperationAbortedError,
|
|
32
|
+
SyncError,
|
|
33
|
+
WormholeError,
|
|
34
|
+
} from './src/domain/errors/index.js';
|
|
35
|
+
import { checkAborted, createTimeoutSignal } from './src/domain/utils/cancellation.js';
|
|
36
|
+
|
|
37
|
+
// Multi-writer graph support (WARP)
|
|
38
|
+
import WarpGraph from './src/domain/WarpGraph.js';
|
|
39
|
+
import {
|
|
40
|
+
createNodeAdd,
|
|
41
|
+
createNodeTombstone,
|
|
42
|
+
createEdgeAdd,
|
|
43
|
+
createEdgeTombstone,
|
|
44
|
+
createPropSet,
|
|
45
|
+
createInlineValue,
|
|
46
|
+
createBlobValue,
|
|
47
|
+
createEventId,
|
|
48
|
+
} from './src/domain/types/WarpTypes.js';
|
|
49
|
+
import { migrateV4toV5 } from './src/domain/services/MigrationService.js';
|
|
50
|
+
import QueryBuilder from './src/domain/services/QueryBuilder.js';
|
|
51
|
+
import ObserverView from './src/domain/services/ObserverView.js';
|
|
52
|
+
import { computeTranslationCost } from './src/domain/services/TranslationCost.js';
|
|
53
|
+
import {
|
|
54
|
+
encodeEdgePropKey,
|
|
55
|
+
decodeEdgePropKey,
|
|
56
|
+
isEdgePropKey,
|
|
57
|
+
} from './src/domain/services/KeyCodec.js';
|
|
58
|
+
import {
|
|
59
|
+
createTickReceipt,
|
|
60
|
+
canonicalJson as tickReceiptCanonicalJson,
|
|
61
|
+
OP_TYPES as TICK_RECEIPT_OP_TYPES,
|
|
62
|
+
RESULT_TYPES as TICK_RECEIPT_RESULT_TYPES,
|
|
63
|
+
} from './src/domain/types/TickReceipt.js';
|
|
64
|
+
|
|
65
|
+
// Provenance payload (HOLOGRAM)
|
|
66
|
+
import ProvenancePayload from './src/domain/services/ProvenancePayload.js';
|
|
67
|
+
|
|
68
|
+
// Boundary Transition Records (HOLOGRAM)
|
|
69
|
+
import {
|
|
70
|
+
createBTR,
|
|
71
|
+
verifyBTR,
|
|
72
|
+
replayBTR,
|
|
73
|
+
serializeBTR,
|
|
74
|
+
deserializeBTR,
|
|
75
|
+
} from './src/domain/services/BoundaryTransitionRecord.js';
|
|
76
|
+
|
|
77
|
+
// Wormhole compression (HOLOGRAM)
|
|
78
|
+
import {
|
|
79
|
+
createWormhole,
|
|
80
|
+
composeWormholes,
|
|
81
|
+
replayWormhole,
|
|
82
|
+
serializeWormhole,
|
|
83
|
+
deserializeWormhole,
|
|
84
|
+
} from './src/domain/services/WormholeService.js';
|
|
85
|
+
|
|
86
|
+
const TraversalService = CommitDagTraversalService;
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
GitGraphAdapter,
|
|
90
|
+
GraphNode,
|
|
91
|
+
BitmapIndexBuilder,
|
|
92
|
+
BitmapIndexReader,
|
|
93
|
+
IndexRebuildService,
|
|
94
|
+
HealthCheckService,
|
|
95
|
+
HealthStatus,
|
|
96
|
+
CommitDagTraversalService,
|
|
97
|
+
TraversalService,
|
|
98
|
+
GraphPersistencePort,
|
|
99
|
+
IndexStoragePort,
|
|
100
|
+
|
|
101
|
+
// Logging infrastructure
|
|
102
|
+
LoggerPort,
|
|
103
|
+
NoOpLogger,
|
|
104
|
+
ConsoleLogger,
|
|
105
|
+
LogLevel,
|
|
106
|
+
|
|
107
|
+
// Clock infrastructure
|
|
108
|
+
ClockPort,
|
|
109
|
+
ClockAdapter,
|
|
110
|
+
PerformanceClockAdapter,
|
|
111
|
+
GlobalClockAdapter,
|
|
112
|
+
|
|
113
|
+
// Error types for integrity failure handling
|
|
114
|
+
ForkError,
|
|
115
|
+
IndexError,
|
|
116
|
+
QueryError,
|
|
117
|
+
SchemaUnsupportedError,
|
|
118
|
+
ShardLoadError,
|
|
119
|
+
ShardCorruptionError,
|
|
120
|
+
ShardValidationError,
|
|
121
|
+
StorageError,
|
|
122
|
+
TraversalError,
|
|
123
|
+
OperationAbortedError,
|
|
124
|
+
SyncError,
|
|
125
|
+
WormholeError,
|
|
126
|
+
|
|
127
|
+
// Cancellation utilities
|
|
128
|
+
checkAborted,
|
|
129
|
+
createTimeoutSignal,
|
|
130
|
+
|
|
131
|
+
// Multi-writer graph support (WARP)
|
|
132
|
+
WarpGraph,
|
|
133
|
+
QueryBuilder,
|
|
134
|
+
ObserverView,
|
|
135
|
+
computeTranslationCost,
|
|
136
|
+
|
|
137
|
+
// WARP type creators
|
|
138
|
+
createNodeAdd,
|
|
139
|
+
createNodeTombstone,
|
|
140
|
+
createEdgeAdd,
|
|
141
|
+
createEdgeTombstone,
|
|
142
|
+
createPropSet,
|
|
143
|
+
createInlineValue,
|
|
144
|
+
createBlobValue,
|
|
145
|
+
createEventId,
|
|
146
|
+
|
|
147
|
+
// Key codec utilities (BULKHEAD)
|
|
148
|
+
encodeEdgePropKey,
|
|
149
|
+
decodeEdgePropKey,
|
|
150
|
+
isEdgePropKey,
|
|
151
|
+
|
|
152
|
+
// WARP migration
|
|
153
|
+
migrateV4toV5,
|
|
154
|
+
|
|
155
|
+
// Tick receipts (LIGHTHOUSE)
|
|
156
|
+
createTickReceipt,
|
|
157
|
+
tickReceiptCanonicalJson,
|
|
158
|
+
TICK_RECEIPT_OP_TYPES,
|
|
159
|
+
TICK_RECEIPT_RESULT_TYPES,
|
|
160
|
+
|
|
161
|
+
// Provenance payload (HOLOGRAM)
|
|
162
|
+
ProvenancePayload,
|
|
163
|
+
|
|
164
|
+
// Boundary Transition Records (HOLOGRAM)
|
|
165
|
+
createBTR,
|
|
166
|
+
verifyBTR,
|
|
167
|
+
replayBTR,
|
|
168
|
+
serializeBTR,
|
|
169
|
+
deserializeBTR,
|
|
170
|
+
|
|
171
|
+
// Wormhole compression (HOLOGRAM)
|
|
172
|
+
createWormhole,
|
|
173
|
+
composeWormholes,
|
|
174
|
+
replayWormhole,
|
|
175
|
+
serializeWormhole,
|
|
176
|
+
deserializeWormhole,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// WarpGraph is the primary API for V7
|
|
180
|
+
export default WarpGraph;
|
package/package.json
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@git-stunts/git-warp",
|
|
3
|
+
"version": "10.1.1",
|
|
4
|
+
"description": "Deterministic WARP graph over Git: graph-native storage, traversal, and tooling.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"author": "James Ross <james@flyingrobots.dev>",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/git-stunts/git-warp.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/git-stunts/git-warp#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/git-stunts/git-warp/issues"
|
|
15
|
+
},
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=20.0.0"
|
|
18
|
+
},
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"main": "./index.js",
|
|
21
|
+
"types": "./index.d.ts",
|
|
22
|
+
"bin": {
|
|
23
|
+
"warp-graph": "./bin/warp-graph.js",
|
|
24
|
+
"git-warp": "./bin/git-warp"
|
|
25
|
+
},
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./index.d.ts",
|
|
29
|
+
"import": "./index.js",
|
|
30
|
+
"default": "./index.js"
|
|
31
|
+
},
|
|
32
|
+
"./node": {
|
|
33
|
+
"types": "./index.d.ts",
|
|
34
|
+
"import": "./src/domain/entities/GraphNode.js",
|
|
35
|
+
"default": "./src/domain/entities/GraphNode.js"
|
|
36
|
+
},
|
|
37
|
+
"./visualization": {
|
|
38
|
+
"import": "./src/visualization/index.js",
|
|
39
|
+
"default": "./src/visualization/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./package.json": "./package.json"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"bin/warp-graph.js",
|
|
45
|
+
"bin/git-warp",
|
|
46
|
+
"src",
|
|
47
|
+
"index.js",
|
|
48
|
+
"index.d.ts",
|
|
49
|
+
"README.md",
|
|
50
|
+
"LICENSE",
|
|
51
|
+
"NOTICE",
|
|
52
|
+
"SECURITY.md",
|
|
53
|
+
"scripts/install-git-warp.sh",
|
|
54
|
+
"scripts/uninstall-git-warp.sh"
|
|
55
|
+
],
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"access": "public"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"lint": "eslint .",
|
|
61
|
+
"lint:links": "lychee --config .lychee.toml '**/*.md'",
|
|
62
|
+
"format": "prettier --write .",
|
|
63
|
+
"test": "sh -c 'if [ \"$GIT_STUNTS_DOCKER\" = \"1\" ]; then vitest run test/unit \"$@\"; else docker compose run --build --rm test npm run test:local -- \"$@\"; fi' --",
|
|
64
|
+
"test:local": "vitest run test/unit",
|
|
65
|
+
"test:watch": "vitest",
|
|
66
|
+
"test:coverage": "vitest run --coverage test/unit",
|
|
67
|
+
"benchmark": "sh -c 'if [ \"$GIT_STUNTS_DOCKER\" = \"1\" ]; then vitest bench --run test/benchmark \"$@\"; else docker compose run --build --rm test npm run benchmark:local -- \"$@\"; fi' --",
|
|
68
|
+
"benchmark:local": "vitest bench --run test/benchmark",
|
|
69
|
+
"demo": "cd examples && docker compose up -d && docker compose exec demo bash",
|
|
70
|
+
"demo:setup": "cd examples && docker compose up -d && docker compose exec demo sh -c 'cd /app && npm install --silent && cd /demo && node /app/examples/setup.js'",
|
|
71
|
+
"demo:explore": "cd examples && docker compose exec demo node /app/examples/explore.js",
|
|
72
|
+
"demo:inspect": "cd examples && docker compose exec demo node /app/examples/inspect-index.js",
|
|
73
|
+
"demo:lagrangian": "cd examples && docker compose exec demo node /app/examples/lagrangian-path.js",
|
|
74
|
+
"demo:bench-streaming": "cd examples && docker compose up -d && docker compose exec demo node /app/examples/streaming-benchmark.js",
|
|
75
|
+
"demo:bench-traversal": "cd examples && docker compose up -d && docker compose exec demo node /app/examples/traversal-benchmark.js",
|
|
76
|
+
"demo:down": "cd examples && docker compose down -v",
|
|
77
|
+
"roadmap": "node scripts/roadmap.js",
|
|
78
|
+
"setup:hooks": "node scripts/setup-hooks.js",
|
|
79
|
+
"prepare": "patch-package && node scripts/setup-hooks.js",
|
|
80
|
+
"prepack": "npm run lint && npm run test:local",
|
|
81
|
+
"install:git-warp": "bash scripts/install-git-warp.sh",
|
|
82
|
+
"uninstall:git-warp": "bash scripts/uninstall-git-warp.sh"
|
|
83
|
+
},
|
|
84
|
+
"dependencies": {
|
|
85
|
+
"@git-stunts/alfred": "^0.4.0",
|
|
86
|
+
"@git-stunts/plumbing": "^2.8.0",
|
|
87
|
+
"@git-stunts/trailer-codec": "^2.1.1",
|
|
88
|
+
"boxen": "^7.1.1",
|
|
89
|
+
"cbor-x": "^1.6.0",
|
|
90
|
+
"chalk": "^5.3.0",
|
|
91
|
+
"cli-table3": "^0.6.3",
|
|
92
|
+
"elkjs": "^0.11.0",
|
|
93
|
+
"figures": "^6.0.1",
|
|
94
|
+
"roaring": "^2.7.0",
|
|
95
|
+
"string-width": "^7.1.0",
|
|
96
|
+
"wrap-ansi": "^9.0.0",
|
|
97
|
+
"zod": "^3.24.1"
|
|
98
|
+
},
|
|
99
|
+
"devDependencies": {
|
|
100
|
+
"@eslint/js": "^9.17.0",
|
|
101
|
+
"@git-stunts/docker-guard": "^0.1.0",
|
|
102
|
+
"@types/node": "^22.15.29",
|
|
103
|
+
"@typescript-eslint/eslint-plugin": "^8.54.0",
|
|
104
|
+
"@typescript-eslint/parser": "^8.54.0",
|
|
105
|
+
"eslint": "^9.17.0",
|
|
106
|
+
"fast-check": "^4.5.3",
|
|
107
|
+
"patch-package": "^8.0.0",
|
|
108
|
+
"prettier": "^3.4.2",
|
|
109
|
+
"typescript": "^5.9.3",
|
|
110
|
+
"typescript-eslint": "^8.54.0",
|
|
111
|
+
"vitest": "^2.1.8"
|
|
112
|
+
},
|
|
113
|
+
"keywords": [
|
|
114
|
+
"git",
|
|
115
|
+
"git-stunts",
|
|
116
|
+
"warp",
|
|
117
|
+
"graph",
|
|
118
|
+
"graph-database",
|
|
119
|
+
"dag",
|
|
120
|
+
"merkle",
|
|
121
|
+
"commit-graph",
|
|
122
|
+
"content-addressable",
|
|
123
|
+
"hexagonal",
|
|
124
|
+
"ddd",
|
|
125
|
+
"invisible-storage",
|
|
126
|
+
"empty-tree"
|
|
127
|
+
],
|
|
128
|
+
"packageManager": "npm@10"
|
|
129
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REPO_URL=${GIT_WARP_REPO_URL:-https://github.com/git-stunts/git-warp.git}
|
|
5
|
+
INSTALL_DIR=${GIT_WARP_HOME:-$HOME/.git-warp}
|
|
6
|
+
PROFILE_FILE=${GIT_WARP_PROFILE:-}
|
|
7
|
+
FORCE_CLONE=0
|
|
8
|
+
DRY_RUN=0
|
|
9
|
+
SILENT=0
|
|
10
|
+
SKIP_PROFILE=0
|
|
11
|
+
|
|
12
|
+
usage() {
|
|
13
|
+
cat <<'USAGE'
|
|
14
|
+
Git Warp bootstrap installer
|
|
15
|
+
|
|
16
|
+
Usage: install-git-warp.sh [options]
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--force overwrite existing installation directory
|
|
20
|
+
--profile FILE shell profile to update (default: auto-detect)
|
|
21
|
+
--dry-run show what would happen without making changes
|
|
22
|
+
--silent reduce logging
|
|
23
|
+
--no-profile do not modify any shell profile (print instructions instead)
|
|
24
|
+
-h, --help show this help
|
|
25
|
+
USAGE
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
log() { [ "$SILENT" -eq 1 ] || echo "[git-warp-install] $*"; }
|
|
29
|
+
run() {
|
|
30
|
+
if [ "$DRY_RUN" -eq 1 ]; then
|
|
31
|
+
printf '+ '
|
|
32
|
+
printf '%q ' "$@"
|
|
33
|
+
printf '\n'
|
|
34
|
+
return 0
|
|
35
|
+
fi
|
|
36
|
+
"$@" || return $?
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
resolve_path() {
|
|
40
|
+
local raw="$1"
|
|
41
|
+
[ -n "$raw" ] || return 1
|
|
42
|
+
|
|
43
|
+
local path="$raw"
|
|
44
|
+
case "$path" in
|
|
45
|
+
~) path="$HOME" ;;
|
|
46
|
+
~/*) path="$HOME/${path#~/}" ;;
|
|
47
|
+
esac
|
|
48
|
+
|
|
49
|
+
if [ "${path#/}" = "$path" ]; then
|
|
50
|
+
path="$PWD/$path"
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
local current="/"
|
|
54
|
+
local suffix="${path#/}"
|
|
55
|
+
local IFS='/'
|
|
56
|
+
# shellcheck disable=SC2206
|
|
57
|
+
local parts=( $suffix )
|
|
58
|
+
local part candidate
|
|
59
|
+
|
|
60
|
+
for part in "${parts[@]}"; do
|
|
61
|
+
case "$part" in
|
|
62
|
+
''|.)
|
|
63
|
+
continue
|
|
64
|
+
;;
|
|
65
|
+
..)
|
|
66
|
+
current="${current%/*}"
|
|
67
|
+
[ -n "$current" ] || current="/"
|
|
68
|
+
continue
|
|
69
|
+
;;
|
|
70
|
+
esac
|
|
71
|
+
|
|
72
|
+
if [ "$current" = "/" ]; then
|
|
73
|
+
candidate="/$part"
|
|
74
|
+
else
|
|
75
|
+
candidate="$current/$part"
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
if [ -d "$candidate" ]; then
|
|
79
|
+
current="$(cd "$candidate" 2>/dev/null && pwd -P)" || return 1
|
|
80
|
+
else
|
|
81
|
+
current="$candidate"
|
|
82
|
+
fi
|
|
83
|
+
done
|
|
84
|
+
|
|
85
|
+
printf '%s' "$current"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
while [ $# -gt 0 ]; do
|
|
89
|
+
case "$1" in
|
|
90
|
+
--force) FORCE_CLONE=1 ;;
|
|
91
|
+
--dry-run) DRY_RUN=1 ;;
|
|
92
|
+
--silent) SILENT=1 ;;
|
|
93
|
+
--no-profile) SKIP_PROFILE=1 ;;
|
|
94
|
+
--profile)
|
|
95
|
+
shift || { usage; exit 1; }
|
|
96
|
+
PROFILE_FILE="$1"
|
|
97
|
+
;;
|
|
98
|
+
-h|--help)
|
|
99
|
+
usage
|
|
100
|
+
exit 0
|
|
101
|
+
;;
|
|
102
|
+
*)
|
|
103
|
+
echo "Unknown flag: $1" >&2
|
|
104
|
+
usage
|
|
105
|
+
exit 1
|
|
106
|
+
;;
|
|
107
|
+
esac
|
|
108
|
+
shift || break
|
|
109
|
+
done
|
|
110
|
+
|
|
111
|
+
if [ -z "$PROFILE_FILE" ]; then
|
|
112
|
+
if [ -n "${ZDOTDIR:-}" ] && [ -f "$ZDOTDIR/.zshrc" ]; then
|
|
113
|
+
PROFILE_FILE="$ZDOTDIR/.zshrc"
|
|
114
|
+
elif [ -f "$HOME/.zshrc" ]; then
|
|
115
|
+
PROFILE_FILE="$HOME/.zshrc"
|
|
116
|
+
elif [ -f "$HOME/.bashrc" ]; then
|
|
117
|
+
PROFILE_FILE="$HOME/.bashrc"
|
|
118
|
+
elif [ -f "$HOME/.bash_profile" ]; then
|
|
119
|
+
PROFILE_FILE="$HOME/.bash_profile"
|
|
120
|
+
elif [ -f "$HOME/.profile" ]; then
|
|
121
|
+
PROFILE_FILE="$HOME/.profile"
|
|
122
|
+
fi
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
if [ -z "$INSTALL_DIR" ]; then
|
|
126
|
+
echo "Error: GIT_WARP_HOME (install directory) must not be empty" >&2
|
|
127
|
+
exit 1
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
RESOLVED_INSTALL_DIR=$(resolve_path "$INSTALL_DIR")
|
|
131
|
+
if [ -z "$RESOLVED_INSTALL_DIR" ]; then
|
|
132
|
+
echo "Error: unable to resolve install path '$INSTALL_DIR'" >&2
|
|
133
|
+
exit 1
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
case "$RESOLVED_INSTALL_DIR" in
|
|
137
|
+
/|/root|/root/*)
|
|
138
|
+
echo "Error: refusing to install into $RESOLVED_INSTALL_DIR" >&2
|
|
139
|
+
exit 1
|
|
140
|
+
;;
|
|
141
|
+
esac
|
|
142
|
+
|
|
143
|
+
ALLOWED_BASES=${GIT_WARP_ALLOWED_BASES:-$HOME:/opt/git-warp}
|
|
144
|
+
IFS=':' read -r -a _git_warp_allowed <<< "$ALLOWED_BASES"
|
|
145
|
+
allowed_ok=0
|
|
146
|
+
for base in "${_git_warp_allowed[@]}"; do
|
|
147
|
+
[ -z "$base" ] && continue
|
|
148
|
+
resolved_base=$(resolve_path "$base" 2>/dev/null || true)
|
|
149
|
+
[ -z "$resolved_base" ] && continue
|
|
150
|
+
case "$RESOLVED_INSTALL_DIR" in
|
|
151
|
+
"$resolved_base"|"$resolved_base"/*)
|
|
152
|
+
allowed_ok=1
|
|
153
|
+
break
|
|
154
|
+
;;
|
|
155
|
+
esac
|
|
156
|
+
done
|
|
157
|
+
unset _git_warp_allowed
|
|
158
|
+
|
|
159
|
+
if [ "$allowed_ok" -ne 1 ]; then
|
|
160
|
+
echo "Error: install directory $RESOLVED_INSTALL_DIR is outside permitted bases ($ALLOWED_BASES)" >&2
|
|
161
|
+
exit 1
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
INSTALL_DIR="$RESOLVED_INSTALL_DIR"
|
|
165
|
+
log "Install dir: $INSTALL_DIR"
|
|
166
|
+
if [ -d "$INSTALL_DIR" ]; then
|
|
167
|
+
if [ "$FORCE_CLONE" -eq 1 ]; then
|
|
168
|
+
if [ -L "$INSTALL_DIR" ]; then
|
|
169
|
+
echo "Error: refusing to remove symlinked install dir ($INSTALL_DIR). Remove it manually first." >&2
|
|
170
|
+
exit 1
|
|
171
|
+
fi
|
|
172
|
+
log "Removing existing directory"
|
|
173
|
+
run rm -rf "$INSTALL_DIR"
|
|
174
|
+
else
|
|
175
|
+
log "Directory already exists; pulling latest"
|
|
176
|
+
if ! git -C "$INSTALL_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
177
|
+
echo "Error: $INSTALL_DIR exists but is not a git repository (use --force to replace it)" >&2
|
|
178
|
+
exit 1
|
|
179
|
+
fi
|
|
180
|
+
default_branch=$(git -C "$INSTALL_DIR" remote show origin 2>/dev/null | awk '/HEAD branch/ {print $NF}')
|
|
181
|
+
if [ -z "$default_branch" ]; then
|
|
182
|
+
for candidate in main master; do
|
|
183
|
+
if git -C "$INSTALL_DIR" show-ref --verify --quiet "refs/remotes/origin/$candidate"; then
|
|
184
|
+
default_branch="$candidate"
|
|
185
|
+
break
|
|
186
|
+
fi
|
|
187
|
+
done
|
|
188
|
+
fi
|
|
189
|
+
if [ -z "$default_branch" ]; then
|
|
190
|
+
echo "Error: unable to determine origin default branch for $INSTALL_DIR" >&2
|
|
191
|
+
exit 1
|
|
192
|
+
fi
|
|
193
|
+
run git -C "$INSTALL_DIR" fetch origin "$default_branch"
|
|
194
|
+
run git -C "$INSTALL_DIR" reset --hard "origin/$default_branch"
|
|
195
|
+
fi
|
|
196
|
+
else
|
|
197
|
+
log "Cloning repo from $REPO_URL"
|
|
198
|
+
run git clone "$REPO_URL" "$INSTALL_DIR"
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
if [ "$DRY_RUN" -eq 0 ]; then
|
|
202
|
+
log "Installing dependencies"
|
|
203
|
+
if [ ! -f "$INSTALL_DIR/package.json" ]; then
|
|
204
|
+
log "Error: package.json not found in $INSTALL_DIR"
|
|
205
|
+
exit 1
|
|
206
|
+
fi
|
|
207
|
+
(cd "$INSTALL_DIR" && npm install ${SILENT:+--silent})
|
|
208
|
+
if [ ! -f "$INSTALL_DIR/bin/git-warp" ]; then
|
|
209
|
+
log "Error: expected $INSTALL_DIR/bin/git-warp to exist"
|
|
210
|
+
exit 1
|
|
211
|
+
fi
|
|
212
|
+
if [ ! -x "$INSTALL_DIR/bin/git-warp" ]; then
|
|
213
|
+
chmod +x "$INSTALL_DIR/bin/git-warp"
|
|
214
|
+
fi
|
|
215
|
+
else
|
|
216
|
+
log "Would install dependencies"
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
BIN_LINE="export PATH=\"$INSTALL_DIR/bin:\$PATH\""
|
|
220
|
+
HOME_LINE="export GIT_WARP_HOME=\"$INSTALL_DIR\""
|
|
221
|
+
PROFILE_UPDATED=0
|
|
222
|
+
|
|
223
|
+
if [ "$SKIP_PROFILE" -eq 0 ] && [ -n "$PROFILE_FILE" ]; then
|
|
224
|
+
touch "$PROFILE_FILE"
|
|
225
|
+
if [ "$DRY_RUN" -eq 0 ]; then
|
|
226
|
+
if [ ! -f "$PROFILE_FILE.bak" ]; then
|
|
227
|
+
log "Creating backup $PROFILE_FILE.bak"
|
|
228
|
+
cp "$PROFILE_FILE" "$PROFILE_FILE.bak"
|
|
229
|
+
fi
|
|
230
|
+
if ! grep -E "^[[:space:]]*export[[:space:]]+GIT_WARP_HOME=" "$PROFILE_FILE" >/dev/null 2>&1; then
|
|
231
|
+
log "Updating $PROFILE_FILE"
|
|
232
|
+
printf '\n# Git Warp\nexport GIT_WARP_HOME="%s"\nexport PATH="%s/bin:$PATH"\n' "$INSTALL_DIR" "$INSTALL_DIR" >> "$PROFILE_FILE"
|
|
233
|
+
PROFILE_UPDATED=1
|
|
234
|
+
else
|
|
235
|
+
log "$PROFILE_FILE already references GIT_WARP_HOME; skipping"
|
|
236
|
+
fi
|
|
237
|
+
else
|
|
238
|
+
log "Would append env vars to $PROFILE_FILE"
|
|
239
|
+
fi
|
|
240
|
+
else
|
|
241
|
+
log "No shell profile updated; export vars manually:"
|
|
242
|
+
log " $HOME_LINE"
|
|
243
|
+
log " $BIN_LINE"
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
cat <<INFO
|
|
247
|
+
|
|
248
|
+
Git Warp installed!
|
|
249
|
+
Reload your shell or run:
|
|
250
|
+
$HOME_LINE
|
|
251
|
+
$BIN_LINE
|
|
252
|
+
Then test with:
|
|
253
|
+
git warp --help
|
|
254
|
+
INFO
|
|
255
|
+
|
|
256
|
+
if [ "$PROFILE_UPDATED" -eq 1 ]; then
|
|
257
|
+
echo "(Appended PATH setup to $PROFILE_FILE)"
|
|
258
|
+
fi
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
INSTALL_DIR=${GIT_WARP_HOME:-$HOME/.git-warp}
|
|
5
|
+
PROFILE_FILE=${GIT_WARP_PROFILE:-}
|
|
6
|
+
DRY_RUN=0
|
|
7
|
+
SILENT=0
|
|
8
|
+
NO_BACKUP=0
|
|
9
|
+
|
|
10
|
+
usage() {
|
|
11
|
+
cat <<'USAGE'
|
|
12
|
+
Git Warp uninstaller
|
|
13
|
+
|
|
14
|
+
Usage: uninstall-git-warp.sh [options]
|
|
15
|
+
|
|
16
|
+
Options:
|
|
17
|
+
--dry-run show actions without performing them
|
|
18
|
+
--silent reduce logging
|
|
19
|
+
--no-backup do not create profile backups before editing
|
|
20
|
+
--profile FILE explicit profile to edit (default: auto-detect)
|
|
21
|
+
-h, --help show this help
|
|
22
|
+
USAGE
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
log() { [ "$SILENT" -eq 1 ] || echo "[git-warp-uninstall] $*"; }
|
|
26
|
+
run() {
|
|
27
|
+
if [ "$DRY_RUN" -eq 1 ]; then
|
|
28
|
+
printf '+ '
|
|
29
|
+
printf '%q ' "$@"
|
|
30
|
+
printf '\n'
|
|
31
|
+
return 0
|
|
32
|
+
fi
|
|
33
|
+
"$@" || return $?
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
sanitize_profile() {
|
|
37
|
+
local profile="$1" install_dir="$2"
|
|
38
|
+
local tmp
|
|
39
|
+
tmp=$(mktemp) || return 1
|
|
40
|
+
if ! awk -v dir="$install_dir" '
|
|
41
|
+
{
|
|
42
|
+
stripped=$0
|
|
43
|
+
sub(/^[[:space:]]+/, "", stripped)
|
|
44
|
+
sub(/[[:space:]]+$/, "", stripped)
|
|
45
|
+
if (stripped == "# Git Warp") next
|
|
46
|
+
if (index($0, dir) > 0) {
|
|
47
|
+
if (stripped ~ /^export[[:space:]]+GIT_WARP_HOME=/) next
|
|
48
|
+
if (stripped ~ /^export[[:space:]]+PATH=/ && index($0, dir "/bin") > 0) next
|
|
49
|
+
}
|
|
50
|
+
print $0
|
|
51
|
+
}
|
|
52
|
+
' "$profile" > "$tmp"; then
|
|
53
|
+
rm -f "$tmp"
|
|
54
|
+
return 1
|
|
55
|
+
fi
|
|
56
|
+
mv "$tmp" "$profile"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
while [ $# -gt 0 ]; do
|
|
60
|
+
case "$1" in
|
|
61
|
+
--dry-run) DRY_RUN=1 ;;
|
|
62
|
+
--silent) SILENT=1 ;;
|
|
63
|
+
--no-backup) NO_BACKUP=1 ;;
|
|
64
|
+
--profile)
|
|
65
|
+
shift || { usage; exit 1; }
|
|
66
|
+
PROFILE_FILE="$1"
|
|
67
|
+
;;
|
|
68
|
+
-h|--help)
|
|
69
|
+
usage
|
|
70
|
+
exit 0
|
|
71
|
+
;;
|
|
72
|
+
*)
|
|
73
|
+
echo "Unknown flag: $1" >&2
|
|
74
|
+
usage
|
|
75
|
+
exit 1
|
|
76
|
+
;;
|
|
77
|
+
esac
|
|
78
|
+
shift || break
|
|
79
|
+
done
|
|
80
|
+
|
|
81
|
+
if [ -z "$PROFILE_FILE" ]; then
|
|
82
|
+
if [ -n "${ZDOTDIR:-}" ] && [ -f "$ZDOTDIR/.zshrc" ]; then
|
|
83
|
+
PROFILE_FILE="$ZDOTDIR/.zshrc"
|
|
84
|
+
elif [ -f "$HOME/.zshrc" ]; then
|
|
85
|
+
PROFILE_FILE="$HOME/.zshrc"
|
|
86
|
+
elif [ -f "$HOME/.bashrc" ]; then
|
|
87
|
+
PROFILE_FILE="$HOME/.bashrc"
|
|
88
|
+
elif [ -f "$HOME/.bash_profile" ]; then
|
|
89
|
+
PROFILE_FILE="$HOME/.bash_profile"
|
|
90
|
+
elif [ -f "$HOME/.profile" ]; then
|
|
91
|
+
PROFILE_FILE="$HOME/.profile"
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
GIT_WARP_TARGET="$INSTALL_DIR/bin/git-warp"
|
|
96
|
+
|
|
97
|
+
if [ -e "/usr/local/bin/git-warp" ]; then
|
|
98
|
+
if [ -L "/usr/local/bin/git-warp" ] && [ "$(readlink "/usr/local/bin/git-warp")" = "$GIT_WARP_TARGET" ]; then
|
|
99
|
+
log "Removing /usr/local/bin/git-warp"
|
|
100
|
+
run rm -f /usr/local/bin/git-warp
|
|
101
|
+
elif cmp -s "/usr/local/bin/git-warp" "$GIT_WARP_TARGET" 2>/dev/null; then
|
|
102
|
+
log "Removing /usr/local/bin/git-warp (matching installed copy)"
|
|
103
|
+
run rm -f /usr/local/bin/git-warp
|
|
104
|
+
else
|
|
105
|
+
log "Skipping removal of /usr/local/bin/git-warp (custom install detected)"
|
|
106
|
+
fi
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
if [ -d "$INSTALL_DIR" ]; then
|
|
110
|
+
if [ -L "$INSTALL_DIR" ]; then
|
|
111
|
+
log "Refusing to remove symlinked install dir $INSTALL_DIR; remove manually"
|
|
112
|
+
else
|
|
113
|
+
log "Removing $INSTALL_DIR"
|
|
114
|
+
run rm -rf "$INSTALL_DIR"
|
|
115
|
+
fi
|
|
116
|
+
else
|
|
117
|
+
log "Install directory $INSTALL_DIR not found"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
if [ -n "$PROFILE_FILE" ] && [ -f "$PROFILE_FILE" ]; then
|
|
121
|
+
if [ "$DRY_RUN" -eq 0 ] && [ "$NO_BACKUP" -eq 0 ]; then
|
|
122
|
+
if [ ! -f "$PROFILE_FILE.git-warp.bak" ]; then
|
|
123
|
+
log "Creating backup $PROFILE_FILE.git-warp.bak"
|
|
124
|
+
cp "$PROFILE_FILE" "$PROFILE_FILE.git-warp.bak"
|
|
125
|
+
fi
|
|
126
|
+
fi
|
|
127
|
+
log "Cleaning Git Warp lines from $PROFILE_FILE"
|
|
128
|
+
if [ "$DRY_RUN" -eq 1 ]; then
|
|
129
|
+
echo "+ removing Git Warp entries from $PROFILE_FILE"
|
|
130
|
+
else
|
|
131
|
+
if ! sanitize_profile "$PROFILE_FILE" "$INSTALL_DIR"; then
|
|
132
|
+
log "Error: failed to clean $PROFILE_FILE; leaving original in place."
|
|
133
|
+
fi
|
|
134
|
+
fi
|
|
135
|
+
else
|
|
136
|
+
log "Profile file not found or unspecified; remove PATH/GIT_WARP_HOME entries manually if needed."
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
log "Git Warp uninstall complete"
|