Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions docs/project-overview-pdr.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ Use `TLC_CODE_DIR` environment variable to customize the base directory.
### 2. Repository Management (`pull-repos`)
Clones or updates Odoo and OCA repositories:
- **Sources**: Official Odoo repos and OCA GitHub repos
- **Speed**: Shallow clones (depth=1) for bandwidth efficiency
- **Speed**: Shallow clones (depth=1) by default for bandwidth efficiency
- **Full History**: Use `--full-history` flag to fetch complete commit history
- **Parallelization**: Multiple repos cloned/updated simultaneously
- **Operations**: Clone new repos, fetch and hard-reset existing ones

Expand Down Expand Up @@ -233,15 +234,40 @@ Clone missing repositories and update existing ones.
**Options**:
- `-f, --filter`: Filter repositories by name (repeatable, e.g., `-f server-tools -f web`)
- `--dry-run`: Preview operations without executing
- `--full-history`: Fetch full commit history instead of shallow clone (depth=1)
- `--newcomer / --no-newcomer`: Enable interactive mode (default: True)

**Behavior**:
- Reads `{CODE_ROOT}/config.toml` (default: `~/code/config.toml`) and loads repo definitions
- For each version, clones missing repos (shallow, depth=1) or updates existing ones
- For each version, clones missing repos (shallow, depth=1 by default) or updates existing ones
- Updates via: git fetch, checkout branch, hard reset to origin/branch
- Executes up to 4 repos in parallel
- Uses GitProgress for progress reporting

**Examples**:
```bash
# Shallow clone (default, faster, less bandwidth)
tlc pull-repos

# Full clone (complete commit history)
tlc pull-repos --full-history

# Filter specific repos with full history
tlc pull-repos --filter odoo --full-history
```

**When to use --full-history**:
- Need to browse full git history
- Performing git bisect operations
- Analyzing commit patterns over time
- Contributing patches based on historical context

**Default behavior (depth=1)**:
- Faster downloads (less data transferred)
- Smaller disk usage
- Sufficient for most development workflows
- Can be "unshallowed" later with `git fetch --unshallow`

**Exit Codes**: 0 on success, 1 if any repo operation fails

---
Expand Down
4 changes: 3 additions & 1 deletion docs/system-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ pull-repos command
│ git checkout {branch}
│ git reset --hard origin/{branch}
│ else:
│ git clone --depth=1 --branch={branch} {url} {path}
│ # Depth controlled by --full-history flag
│ depth = None if full_history else 1
│ git clone --depth={depth} --branch={branch} {url} {path}
│ with GitProgress callback
├─ Aggregate TaskResults
Expand Down
72 changes: 72 additions & 0 deletions tests/test_pull_repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,78 @@ def test_pull_repo_handles_git_exception(tmp_path, mock_git_repo_calls):
assert found_error_description


def test_pull_repo_clones_with_shallow_clone_by_default(tmp_path, mock_git_repo_calls, mock_main_git_progress):
"""Test that repos are cloned with depth=1 by default."""
mock_clone_from, _ = mock_git_repo_calls
progress_mock = MagicMock(spec=Progress)

repo_path = tmp_path / "code" / "odoo" / "odoo" / "16.0"
repo_path.parent.mkdir(parents=True, exist_ok=True)

repo_info = {
"repo_name": "odoo",
"repo_path": repo_path,
"repo_url": ODOO_URLS["odoo"],
"version": "16.0",
}

# Call without full_history parameter (default behavior)
_pull_repo(progress_mock, task, repo_info)

# Verify depth=1 is used
mock_clone_from.assert_called_once()
call_kwargs = mock_clone_from.call_args.kwargs
assert call_kwargs["depth"] == 1


def test_pull_repo_clones_with_full_history_when_flag_set(tmp_path, mock_git_repo_calls, mock_main_git_progress):
"""Test that repos are cloned with full history when --full-history flag is used."""
mock_clone_from, _ = mock_git_repo_calls
progress_mock = MagicMock(spec=Progress)

repo_path = tmp_path / "code" / "odoo" / "odoo" / "16.0"
repo_path.parent.mkdir(parents=True, exist_ok=True)

repo_info = {
"repo_name": "odoo",
"repo_path": repo_path,
"repo_url": ODOO_URLS["odoo"],
"version": "16.0",
}

# Call with full_history=True
_pull_repo(progress_mock, task, repo_info, full_history=True)

# Verify depth=None is used (full clone)
mock_clone_from.assert_called_once()
call_kwargs = mock_clone_from.call_args.kwargs
assert call_kwargs["depth"] is None


def test_pull_repo_update_existing_ignores_full_history_flag(tmp_path, mock_git_repo_calls, mock_main_git_progress):
"""Test that existing repo updates ignore the full_history flag."""
_, mock_repo_class = mock_git_repo_calls
progress_mock = MagicMock(spec=Progress)

repo_path = tmp_path / "code" / "odoo" / "odoo" / "16.0"
repo_path.mkdir(parents=True, exist_ok=True)

repo_info = {
"repo_name": "odoo",
"repo_path": repo_path,
"repo_url": ODOO_URLS["odoo"],
"version": "16.0",
}

# Call with full_history=True on existing repo
_pull_repo(progress_mock, task, repo_info, full_history=True)

# Verify fetch/reset was called (not clone)
mock_repo_instance = mock_repo_class.return_value
mock_repo_instance.remotes.origin.fetch.assert_called_once_with("16.0")
mock_repo_instance.git.reset.assert_called_once_with("--hard", "origin/16.0")


def test_get_tasks_generates_correct_list(mock_config, tmp_path):
odoo_versions = ["16.0", "17.0"]
repos_config = {"odoo": ["odoo"], "oca": ["server-tools"]}
Expand Down
15 changes: 12 additions & 3 deletions trobz_local/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ def pull_repos( # noqa: C901
),
] = None,
dry_run: bool = typer.Option(False, "--dry-run", help="Prints actions without running."),
full_history: bool = typer.Option(
False,
"--full-history",
help="Fetch full commit history instead of shallow clone (depth=1).",
),
):
"""
Pull/clone Odoo and OCA repos based on config
Expand Down Expand Up @@ -167,7 +172,7 @@ def pull_repos( # noqa: C901
concurrency_tasks.append({
"name": f"{repo_info['repo_name']} ({repo_info['version']})",
"func": _pull_repo,
"args": {"repo_info": repo_info},
"args": {"repo_info": repo_info, "full_history": full_history},
})

results = run_tasks(concurrency_tasks)
Expand Down Expand Up @@ -205,7 +210,7 @@ def _get_tasks(odoo_versions, repos_config, code_root, repo_filter):
return tasks


def _pull_repo(progress: Progress, task_id: TaskID, repo_info: dict):
def _pull_repo(progress: Progress, task_id: TaskID, repo_info: dict, full_history: bool = False):
repo_name = repo_info["repo_name"]
repo_path = repo_info["repo_path"]
repo_url = repo_info["repo_url"]
Expand All @@ -216,12 +221,16 @@ def _pull_repo(progress: Progress, task_id: TaskID, repo_info: dict):
if not repo_path.exists():
progress.update(task_id, description=f"Cloning {repo_name} ({version})")
repo_path.parent.mkdir(parents=True, exist_ok=True)

# Calculate depth based on full_history flag
depth = None if full_history else 1

git.Repo.clone_from(
repo_url,
to_path=repo_path,
branch=version,
progress=GitProgress(progress, task_id, f"Cloning {repo_name} {version}"), # ty: ignore[invalid-argument-type]
depth=1,
depth=depth,
)
else:
progress.update(task_id, description=f"Fetching {repo_name} ({version})")
Expand Down