upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/GETTING_STARTED.md437
1 files changed, 0 insertions, 437 deletions
diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md
deleted file mode 100644
index 7fea590..0000000
--- a/docs/GETTING_STARTED.md
+++ /dev/null
@@ -1,437 +0,0 @@
1# Getting Started with Implementation
2
3This guide helps you start implementing ngit-grasp based on the architecture design.
4
5## Prerequisites
6
7- Rust 1.75 or later
8- Git 2.x
9- Basic understanding of async Rust (tokio)
10- Familiarity with actix-web (helpful)
11- Understanding of Nostr basics (helpful)
12
13## Step 1: Initialize Cargo Project
14
15```bash
16# Create new binary project
17cargo init --name ngit-grasp
18
19# Or if already created:
20cargo build
21```
22
23## Step 2: Add Dependencies
24
25Edit `Cargo.toml`:
26
27```toml
28[package]
29name = "ngit-grasp"
30version = "0.1.0"
31edition = "2021"
32rust-version = "1.75"
33
34[dependencies]
35# HTTP Server
36actix-web = "4"
37actix-cors = "0.7"
38
39# Async Runtime
40tokio = { version = "1", features = ["full"] }
41
42# Git Protocol
43git-http-backend = "0.1.3"
44
45# Nostr
46nostr-sdk = { version = "0.43", features = ["all-nips"] }
47nostr-relay-builder = "0.43"
48
49# Serialization
50serde = { version = "1", features = ["derive"] }
51serde_json = "1"
52
53# Error Handling
54anyhow = "1"
55thiserror = "1"
56
57# Logging
58tracing = "0.1"
59tracing-subscriber = { version = "0.3", features = ["env-filter"] }
60
61# Environment
62dotenv = "0.15"
63
64# Utilities
65async-trait = "0.1"
66futures = "0.3"
67bytes = "1"
68
69[dev-dependencies]
70tokio-test = "0.4"
71```
72
73## Step 3: Project Structure
74
75Create the directory structure:
76
77```bash
78mkdir -p src/{git,nostr,storage}
79mkdir -p tests/{integration,fixtures}
80mkdir -p data/{git,relay}
81```
82
83## Step 4: Configuration Module
84
85Create `src/config.rs`:
86
87```rust
88use anyhow::Result;
89use std::env;
90use std::net::SocketAddr;
91use std::path::PathBuf;
92
93#[derive(Debug, Clone)]
94pub struct Config {
95 pub domain: String,
96 pub owner_npub: String,
97 pub relay_name: String,
98 pub relay_description: String,
99 pub git_data_path: PathBuf,
100 pub relay_data_path: PathBuf,
101 pub bind_address: SocketAddr,
102}
103
104impl Config {
105 pub fn from_env() -> Result<Self> {
106 dotenv::dotenv().ok();
107
108 Ok(Config {
109 domain: env::var("NGIT_DOMAIN")?,
110 owner_npub: env::var("NGIT_OWNER_NPUB")?,
111 relay_name: env::var("NGIT_RELAY_NAME")?,
112 relay_description: env::var("NGIT_RELAY_DESCRIPTION")?,
113 git_data_path: PathBuf::from(
114 env::var("NGIT_GIT_DATA_PATH")
115 .unwrap_or_else(|_| "./data/git".to_string())
116 ),
117 relay_data_path: PathBuf::from(
118 env::var("NGIT_RELAY_DATA_PATH")
119 .unwrap_or_else(|_| "./data/relay".to_string())
120 ),
121 bind_address: env::var("NGIT_BIND_ADDRESS")
122 .unwrap_or_else(|_| "127.0.0.1:8080".to_string())
123 .parse()?,
124 })
125 }
126}
127```
128
129## Step 5: Core Types
130
131Create `src/git/types.rs`:
132
133```rust
134use serde::{Deserialize, Serialize};
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
137pub struct RefUpdate {
138 pub old_oid: String,
139 pub new_oid: String,
140 pub ref_name: String,
141}
142
143impl RefUpdate {
144 pub fn is_create(&self) -> bool {
145 self.old_oid == "0000000000000000000000000000000000000000"
146 }
147
148 pub fn is_delete(&self) -> bool {
149 self.new_oid == "0000000000000000000000000000000000000000"
150 }
151
152 pub fn is_update(&self) -> bool {
153 !self.is_create() && !self.is_delete()
154 }
155}
156
157#[derive(Debug, thiserror::Error)]
158pub enum GitError {
159 #[error("Invalid pkt-line format")]
160 InvalidPktLine,
161
162 #[error("Invalid ref update format")]
163 InvalidRefUpdate,
164
165 #[error("Repository not found: {0}")]
166 RepositoryNotFound(String),
167
168 #[error("Invalid repository path")]
169 InvalidPath,
170}
171```
172
173## Step 6: Main Application State
174
175Create `src/main.rs`:
176
177```rust
178use actix_web::{web, App, HttpServer};
179use anyhow::Result;
180use std::sync::Arc;
181use tracing::info;
182
183mod config;
184mod git;
185mod nostr;
186mod storage;
187
188use config::Config;
189
190#[derive(Clone)]
191pub struct AppState {
192 pub config: Arc<Config>,
193 // TODO: Add NostrClient, RepositoryManager, etc.
194}
195
196#[actix_web::main]
197async fn main() -> Result<()> {
198 // Initialize logging
199 tracing_subscriber::fmt()
200 .with_env_filter(
201 tracing_subscriber::EnvFilter::from_default_env()
202 )
203 .init();
204
205 // Load configuration
206 let config = Config::from_env()?;
207 info!("Starting ngit-grasp on {}", config.bind_address);
208
209 // Create application state
210 let state = AppState {
211 config: Arc::new(config.clone()),
212 };
213
214 // Start HTTP server
215 HttpServer::new(move || {
216 App::new()
217 .app_data(web::Data::new(state.clone()))
218 .configure(git::routes::configure)
219 .configure(nostr::routes::configure)
220 })
221 .bind(config.bind_address)?
222 .run()
223 .await?;
224
225 Ok(())
226}
227```
228
229## Step 7: Git Module Skeleton
230
231Create `src/git/mod.rs`:
232
233```rust
234pub mod routes;
235pub mod handler;
236pub mod parser;
237pub mod authorization;
238pub mod types;
239
240pub use types::{RefUpdate, GitError};
241```
242
243Create `src/git/routes.rs`:
244
245```rust
246use actix_web::web;
247
248pub fn configure(cfg: &mut web::ServiceConfig) {
249 cfg.service(
250 web::scope("/{npub}/{identifier}.git")
251 .route("/info/refs", web::get().to(super::handler::info_refs))
252 .route("/git-upload-pack", web::post().to(super::handler::git_upload_pack))
253 .route("/git-receive-pack", web::post().to(super::handler::git_receive_pack))
254 );
255}
256```
257
258## Step 8: First Test
259
260Create `tests/integration/basic_test.rs`:
261
262```rust
263use actix_web::{test, App};
264
265#[actix_web::test]
266async fn test_server_starts() {
267 // TODO: Initialize test app
268 // TODO: Make test request
269 assert!(true);
270}
271```
272
273Run tests:
274
275```bash
276cargo test
277```
278
279## Step 9: Implementation Order
280
281Follow this order for implementation:
282
283### Phase 1: Basic Infrastructure (Week 1)
2841. ✅ Config module
2852. ✅ Main server setup
2863. ✅ Core types
2874. ⏭️ Git pkt-line parser
2885. ⏭️ Ref update parser
2896. ⏭️ Parser tests
290
291### Phase 2: Git Protocol (Week 2)
2921. ⏭️ Git upload-pack handler (read-only)
2932. ⏭️ Repository manager
2943. ⏭️ Path validation and security
2954. ⏭️ Integration tests for cloning
296
297### Phase 3: Nostr Relay (Week 2-3)
2981. ⏭️ Nostr relay setup with nostr-relay-builder
2992. ⏭️ Repository announcement policy
3003. ⏭️ Event hooks for repo creation
3014. ⏭️ NIP-11 configuration
302
303### Phase 4: Authorization (Week 3-4)
3041. ⏭️ Maintainer resolution logic
3052. ⏭️ State validation logic
3063. ⏭️ Git receive-pack with inline validation
3074. ⏭️ Integration tests for pushing
308
309### Phase 5: Polish (Week 4-6)
3101. ⏭️ Error handling improvements
3112. ⏭️ Logging and observability
3123. ⏭️ Performance optimization
3134. ⏭️ GRASP-01 compliance testing
3145. ⏭️ Documentation updates
315
316## Development Workflow
317
318### Running Locally
319
320```bash
321# Copy environment template
322cp .env.example .env
323
324# Edit configuration
325vim .env
326
327# Run in development mode
328cargo run
329
330# With debug logging
331RUST_LOG=debug cargo run
332```
333
334### Testing
335
336```bash
337# Run all tests
338cargo test
339
340# Run with output
341cargo test -- --nocapture
342
343# Run specific test
344cargo test test_parse_ref_updates
345
346# Run integration tests only
347cargo test --test '*'
348```
349
350### Code Quality
351
352```bash
353# Format code
354cargo fmt
355
356# Check formatting
357cargo fmt --check
358
359# Lint
360cargo clippy
361
362# Lint with all features
363cargo clippy --all-features -- -D warnings
364```
365
366## Debugging Tips
367
368### Enable Detailed Logging
369
370```bash
371RUST_LOG=trace cargo run
372```
373
374### Test with Real Git Client
375
376```bash
377# In another terminal, after server is running
378mkdir test-repo && cd test-repo
379git init
380echo "test" > README.md
381git add . && git commit -m "test"
382
383# Try to push (will fail without Nostr setup)
384git remote add origin http://localhost:8080/npub.../test.git
385git push origin main
386```
387
388### Use curl for HTTP Testing
389
390```bash
391# Test info/refs endpoint
392curl -v http://localhost:8080/npub.../test.git/info/refs?service=git-upload-pack
393```
394
395## Common Issues
396
397### "Repository not found"
398- Check that repository announcement was sent to Nostr relay
399- Verify repository was created in git_data_path
400- Check logs for repo creation
401
402### "Push rejected"
403- Verify state event exists on relay
404- Check state event matches push refs
405- Verify maintainer list includes pusher
406
407### "Cannot connect to relay"
408- Check relay is running
409- Verify WebSocket endpoint
410- Check firewall/network settings
411
412## Next Steps
413
414After basic setup:
415
4161. Implement pkt-line parser (see [GIT_PROTOCOL.md](GIT_PROTOCOL.md))
4172. Add comprehensive tests
4183. Implement Nostr relay policies
4194. Add authorization logic
4205. Test with ngit CLI
421
422## Resources
423
424- [ARCHITECTURE.md](ARCHITECTURE.md) - Detailed design
425- [GIT_PROTOCOL.md](GIT_PROTOCOL.md) - Git protocol reference
426- [actix-web docs](https://actix.rs/docs/)
427- [nostr-sdk docs](https://docs.rs/nostr-sdk/)
428- [tokio docs](https://docs.rs/tokio/)
429
430## Getting Help
431
432- Check existing documentation in `docs/`
433- Review reference implementation at `../ngit-relay`
434- Open an issue for questions
435- Read GRASP protocol spec
436
437Good luck! 🚀