6f41fa7cbe
- Install @phosphor-icons/react package - Create centralized Icon component with size/weight/color variants - Create icon registry with 34 icons across 5 categories - Replace all raw Unicode symbols with proper icon components - Add icons to navigation, buttons, status indicators, git operations - Add icon CSS with consistent sizing and spacing - Fix type definitions for Phosphor icon compatibility Quality gates: typecheck ✓, lint ✓, build ✓ (375KB bundle)
207 lines
6.4 KiB
Markdown
207 lines
6.4 KiB
Markdown
# Smart Git URL Parsing Specification
|
|
|
|
## Requirements
|
|
|
|
### Functional Requirements
|
|
|
|
1. **URL Detection**: Detect when a provided URL is a browser URL rather than a git clone URL
|
|
2. **URL Extraction**: Extract the base repository URL from browser URLs
|
|
3. **User Confirmation**: Show extracted URL to user and ask for confirmation
|
|
4. **Flexible Input**: Allow users to proceed with original URL if they prefer
|
|
5. **Multiple Hosts**: Support GitHub, GitLab, Bitbucket, and generic git hosts
|
|
|
|
### Non-Functional Requirements
|
|
|
|
1. **Performance**: URL parsing should be instant (< 100ms)
|
|
2. **Accuracy**: Should correctly identify 95%+ of browser URLs
|
|
3. **User Experience**: Clear, helpful messages without technical jargon
|
|
4. **Backward Compatibility**: Existing valid git URLs should continue to work
|
|
|
|
## API Specification
|
|
|
|
### POST /git-repositories/parse-url
|
|
Parse a URL and determine if it's a valid clone URL or needs correction.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"url": "https://github.com/user/repo/tree/main"
|
|
}
|
|
```
|
|
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"original_url": "https://github.com/user/repo/tree/main",
|
|
"base_url": "https://github.com/user/repo.git",
|
|
"is_valid_clone_url": false,
|
|
"needs_parsing": true,
|
|
"host": "github.com",
|
|
"message": "This URL contains a branch path. The repository URL is: https://github.com/user/repo.git"
|
|
}
|
|
```
|
|
|
|
**Response 200 (already valid):**
|
|
```json
|
|
{
|
|
"original_url": "https://github.com/user/repo.git",
|
|
"base_url": "https://github.com/user/repo.git",
|
|
"is_valid_clone_url": true,
|
|
"needs_parsing": false,
|
|
"host": "github.com",
|
|
"message": "Valid git repository URL"
|
|
}
|
|
```
|
|
|
|
### Enhanced POST /projects/{project_id}/repositories
|
|
Enhanced to return suggestions when URL needs parsing.
|
|
|
|
**New 422 Response:**
|
|
```json
|
|
{
|
|
"detail": "The provided URL appears to be a browser URL, not a git clone URL",
|
|
"suggested_url": "https://github.com/user/repo.git",
|
|
"original_url": "https://github.com/user/repo/tree/main",
|
|
"error_code": "URL_NEEDS_PARSING"
|
|
}
|
|
```
|
|
|
|
**Request Body (with force flag):**
|
|
```json
|
|
{
|
|
"name": "my-repo",
|
|
"remote_url": "https://github.com/user/repo/tree/main",
|
|
"is_mirror": false,
|
|
"force_original_url": true
|
|
}
|
|
```
|
|
|
|
## Data Model
|
|
|
|
### URLParseResult
|
|
```python
|
|
class URLParseResult:
|
|
original_url: str
|
|
base_url: str | None
|
|
is_valid_clone_url: bool
|
|
needs_parsing: bool
|
|
host: str | None
|
|
message: str
|
|
error_code: str | None
|
|
```
|
|
|
|
## URL Parsing Rules
|
|
|
|
### Supported Hosts
|
|
- github.com
|
|
- gitlab.com
|
|
- bitbucket.org
|
|
- Any custom domain with git hosting
|
|
|
|
### GitHub URL Patterns
|
|
```
|
|
https://github.com/{owner}/{repo} → valid
|
|
https://github.com/{owner}/{repo}.git → valid
|
|
https://github.com/{owner}/{repo}/tree/{branch} → extract base
|
|
https://github.com/{owner}/{repo}/blob/{branch}/{path} → extract base
|
|
https://github.com/{owner}/{repo}/pull/{number} → extract base
|
|
https://github.com/{owner}/{repo}/issues/{number} → extract base
|
|
https://github.com/{owner}/{repo}/actions → extract base
|
|
```
|
|
|
|
### GitLab URL Patterns
|
|
```
|
|
https://gitlab.com/{owner}/{repo} → valid
|
|
https://gitlab.com/{owner}/{repo}.git → valid
|
|
https://gitlab.com/{owner}/{repo}/-/tree/{branch} → extract base
|
|
https://gitlab.com/{owner}/{repo}/-/blob/{branch}/{path} → extract base
|
|
https://gitlab.com/{owner}/{repo}/-/merge_requests/{number} → extract base
|
|
```
|
|
|
|
### Bitbucket URL Patterns
|
|
```
|
|
https://bitbucket.org/{owner}/{repo} → valid
|
|
https://bitbucket.org/{owner}/{repo}.git → valid
|
|
https://bitbucket.org/{owner}/{repo}/src/{branch} → extract base
|
|
```
|
|
|
|
### Extraction Algorithm
|
|
1. Parse URL components (scheme, netloc, path, query)
|
|
2. Remove query parameters entirely
|
|
3. Split path by `/`
|
|
4. Remove trailing segments that indicate non-repo paths:
|
|
- `tree/*`, `blob/*`, `pull/*`, `issues/*`, `actions`
|
|
- `-/tree/*`, `-/blob/*`, `-/merge_requests/*`
|
|
- `src/*`
|
|
5. Reconstruct URL with remaining path
|
|
6. Add `.git` suffix if missing (for HTTPS URLs)
|
|
7. Return extracted URL
|
|
|
|
## Frontend Specification
|
|
|
|
### URL Input Component
|
|
- Input field for repository URL
|
|
- Real-time validation (debounced 300ms)
|
|
- Visual indicators:
|
|
- 🟢 Green border: Valid git URL
|
|
- 🟡 Yellow border: Browser URL detected, suggestion shown
|
|
- 🔴 Red border: Invalid/malformed URL
|
|
- Inline suggestion banner below input:
|
|
```
|
|
⚠️ This looks like a browser URL
|
|
Suggested: https://github.com/user/repo.git
|
|
[Use Suggested] [Keep Original]
|
|
```
|
|
|
|
### Confirmation Dialog
|
|
Shown when backend returns 422 with suggestion:
|
|
```
|
|
┌─────────────────────────────────────┐
|
|
│ URL Correction Suggestion │
|
|
├─────────────────────────────────────┤
|
|
│ │
|
|
│ The URL you entered appears to be │
|
|
│ a browser URL, not a git clone URL. │
|
|
│ │
|
|
│ Original: │
|
|
│ https://github.com/user/repo/tree/main│
|
|
│ │
|
|
│ Suggested repository URL: │
|
|
│ https://github.com/user/repo.git │
|
|
│ │
|
|
│ [Use Suggested URL] [Use Original] │
|
|
│ [Cancel] │
|
|
└─────────────────────────────────────┘
|
|
```
|
|
|
|
## Error Codes
|
|
|
|
| Error Code | Description | User Message |
|
|
|------------|-------------|--------------|
|
|
| URL_NEEDS_PARSING | Browser URL detected | "This looks like a browser URL. Did you mean: {suggested_url}?" |
|
|
| INVALID_URL | Malformed URL | "Please enter a valid URL" |
|
|
| UNSUPPORTED_HOST | Unknown git host | "This git host is not supported" |
|
|
| CLONE_FAILED | Git clone failed | "Failed to clone repository: {error}" |
|
|
| AUTH_REQUIRED | Private repo, need auth | "This repository requires authentication" |
|
|
|
|
## Testing Strategy
|
|
|
|
### Unit Tests (URL Parsing)
|
|
- Test all GitHub URL patterns
|
|
- Test all GitLab URL patterns
|
|
- Test all Bitbucket URL patterns
|
|
- Test valid URLs pass through unchanged
|
|
- Test edge cases (subgroups, nested paths, etc.)
|
|
|
|
### Integration Tests
|
|
- Test parse-url endpoint with various URLs
|
|
- Test repository creation with browser URL (should suggest correction)
|
|
- Test repository creation with force flag
|
|
- Test clone operation with corrected URL
|
|
|
|
### Frontend Tests
|
|
- Test URL input validation states
|
|
- Test suggestion banner display
|
|
- Test confirmation dialog flow
|
|
- Test acceptance/rejection of suggestions
|