212 lines
6.0 KiB
Markdown
212 lines
6.0 KiB
Markdown
# Git Interface Redesign Plan
|
|
|
|
## Current Understanding
|
|
|
|
The current git interface consists of standalone functions like `git_clone`, `git_list`, `git_update`, etc. We want to replace this with an object-oriented interface using a builder pattern that allows for method chaining.
|
|
|
|
## New Interface Design
|
|
|
|
### Core Components
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class GitTree {
|
|
+String base_path
|
|
+new(base_path: &str) Result<GitTree, GitError>
|
|
+list() Result<Vec<String>, GitError>
|
|
+find(pattern: &str) Result<Vec<String>, GitError>
|
|
+get(path_pattern: &str) Result<Vec<GitRepo>, GitError>
|
|
}
|
|
|
|
class GitRepo {
|
|
+String path
|
|
+pull() Result<GitRepo, GitError>
|
|
+reset() Result<GitRepo, GitError>
|
|
+push() Result<GitRepo, GitError>
|
|
+commit(message: &str) Result<GitRepo, GitError>
|
|
+has_changes() Result<bool, GitError>
|
|
}
|
|
|
|
GitTree --> GitRepo : creates
|
|
```
|
|
|
|
### Implementation Details
|
|
|
|
1. **GitTree Class**:
|
|
- Constructor takes a base path parameter that specifies where all git repositories will be located
|
|
- Methods for listing and finding repositories
|
|
- A `get()` method that returns one or more GitRepo objects based on a path pattern
|
|
- The `get()` method can also accept a URL (git or http format) and will clone the repository if it doesn't exist
|
|
|
|
2. **GitRepo Class**:
|
|
- Represents a single git repository
|
|
- Methods for common git operations: pull, reset, push, commit
|
|
- Each method returns a Result containing either the GitRepo object (for chaining) or an error
|
|
- If an operation fails, subsequent operations in the chain are skipped
|
|
|
|
3. **Error Handling**:
|
|
- Each method returns a Result type for immediate error handling
|
|
- Errors are propagated up the call chain
|
|
- The existing GitError enum will be reused
|
|
|
|
## Implementation Plan
|
|
|
|
### 1. Create the GitTree and GitRepo Structs in git.rs
|
|
|
|
```rust
|
|
pub struct GitTree {
|
|
base_path: String,
|
|
}
|
|
|
|
pub struct GitRepo {
|
|
path: String,
|
|
}
|
|
```
|
|
|
|
### 2. Implement the GitTree Methods
|
|
|
|
```rust
|
|
impl GitTree {
|
|
pub fn new(base_path: &str) -> Result<Self, GitError> {
|
|
// Validate the base path
|
|
// Create the directory if it doesn't exist
|
|
Ok(GitTree {
|
|
base_path: base_path.to_string(),
|
|
})
|
|
}
|
|
|
|
pub fn list(&self) -> Result<Vec<String>, GitError> {
|
|
// List all git repositories under the base path
|
|
}
|
|
|
|
pub fn find(&self, pattern: &str) -> Result<Vec<String>, GitError> {
|
|
// Find repositories matching the pattern
|
|
}
|
|
|
|
pub fn get(&self, path_pattern: &str) -> Result<Vec<GitRepo>, GitError> {
|
|
// Find repositories matching the pattern
|
|
// Return GitRepo objects for each match
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Implement the GitRepo Methods
|
|
|
|
```rust
|
|
impl GitRepo {
|
|
pub fn pull(&self) -> Result<Self, GitError> {
|
|
// Pull the latest changes
|
|
// Return self for chaining or an error
|
|
}
|
|
|
|
pub fn reset(&self) -> Result<Self, GitError> {
|
|
// Reset any local changes
|
|
// Return self for chaining or an error
|
|
}
|
|
|
|
pub fn push(&self) -> Result<Self, GitError> {
|
|
// Push changes to the remote
|
|
// Return self for chaining or an error
|
|
}
|
|
|
|
pub fn commit(&self, message: &str) -> Result<Self, GitError> {
|
|
// Commit changes with the given message
|
|
// Return self for chaining or an error
|
|
}
|
|
|
|
pub fn has_changes(&self) -> Result<bool, GitError> {
|
|
// Check if the repository has uncommitted changes
|
|
}
|
|
}
|
|
```
|
|
|
|
### 4. Update the Rhai Wrappers in rhai/git.rs
|
|
|
|
```rust
|
|
// Register the GitTree and GitRepo types with Rhai
|
|
pub fn register_git_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
|
// Register the GitTree type
|
|
engine.register_type::<GitTree>();
|
|
engine.register_fn("new", git_tree_new);
|
|
|
|
// Register GitTree methods
|
|
engine.register_fn("list", git_tree_list);
|
|
engine.register_fn("find", git_tree_find);
|
|
engine.register_fn("get", git_tree_get);
|
|
|
|
// Register GitRepo methods
|
|
engine.register_type::<GitRepo>();
|
|
engine.register_fn("pull", git_repo_pull);
|
|
engine.register_fn("reset", git_repo_reset);
|
|
engine.register_fn("push", git_repo_push);
|
|
engine.register_fn("commit", git_repo_commit);
|
|
engine.register_fn("has_changes", git_repo_has_changes);
|
|
|
|
Ok(())
|
|
}
|
|
```
|
|
|
|
### 5. Update Tests and Examples
|
|
|
|
- Update the test files to use the new interface
|
|
- Create new examples demonstrating the builder pattern and method chaining
|
|
|
|
## Usage Examples
|
|
|
|
### Example 1: Basic Repository Operations
|
|
|
|
```rhai
|
|
// Create a new GitTree object
|
|
let git_tree = new("/home/user/code");
|
|
|
|
// List all repositories
|
|
let repos = git_tree.list();
|
|
print(`Found ${repos.len()} repositories`);
|
|
|
|
// Find repositories matching a pattern
|
|
let matching = git_tree.find("my-project*");
|
|
print(`Found ${matching.len()} matching repositories`);
|
|
|
|
// Get a repository and perform operations
|
|
let repo = git_tree.get("my-project")[0];
|
|
let result = repo.pull().reset().commit("Update files").push();
|
|
```
|
|
|
|
### Example 2: Working with Multiple Repositories
|
|
|
|
```rhai
|
|
// Create a new GitTree object
|
|
let git_tree = new("/home/user/code");
|
|
|
|
// Get all repositories matching a pattern
|
|
let repos = git_tree.get("project*");
|
|
print(`Found ${repos.len()} matching repositories`);
|
|
|
|
// Perform operations on all repositories
|
|
for repo in repos {
|
|
let result = repo.pull();
|
|
if result.is_ok() {
|
|
print(`Successfully pulled ${repo.path}`);
|
|
} else {
|
|
print(`Failed to pull ${repo.path}: ${result.error}`);
|
|
}
|
|
}
|
|
```
|
|
|
|
### Example 3: Cloning a Repository
|
|
|
|
```rhai
|
|
// Create a new GitTree object
|
|
let git_tree = new("/home/user/code");
|
|
|
|
// Clone a repository by URL
|
|
let repos = git_tree.get("https://github.com/username/repo.git");
|
|
let repo = repos[0];
|
|
print(`Repository cloned to: ${repo.path}`);
|
|
```
|
|
|
|
## Migration Strategy
|
|
|
|
1. Implement the new interface in git.rs and rhai/git.rs
|
|
2. Update all tests and examples to use the new interface
|
|
3. Remove the old standalone functions |