🚧 Add export feature and refined exclusion info
This commit is contained in:
@@ -295,6 +295,88 @@ class TestExtraction:
|
||||
assert before == after
|
||||
|
||||
|
||||
class TestExportHistory:
|
||||
"""export subcommand: collected history becomes analysis-ready rows."""
|
||||
|
||||
def _collect_two_cycles(self, git_repo: Path, config: dict, tmp_path: Path) -> None:
|
||||
# Cycle 1: one addition with sidecar attribution
|
||||
(git_repo / "config.xml").write_text("<c/>", encoding="utf-8")
|
||||
(git_repo / "config.xml.metadata").write_text(
|
||||
"last_modified_by=DOMAIN\\jsmith\n", encoding="utf-8"
|
||||
)
|
||||
_run(config, tmp_path)
|
||||
# Cycle 2: one deletion (bare D line in the history)
|
||||
(git_repo / "config.xml").unlink()
|
||||
_run(config, tmp_path)
|
||||
|
||||
def test_export_csv_round_trip(
|
||||
self, git_repo: Path, tracker_config: dict, tmp_path: Path
|
||||
) -> None:
|
||||
import csv
|
||||
|
||||
from git_auto_tracker.config import AppConfig
|
||||
from git_auto_tracker.exporting.history import export_history
|
||||
|
||||
self._collect_two_cycles(git_repo, tracker_config, tmp_path)
|
||||
app_config = AppConfig.from_dict(tracker_config, config_dir=tmp_path)
|
||||
output = tmp_path / "history.csv"
|
||||
count = export_history(app_config, output)
|
||||
|
||||
# 3 rows: A config.xml + A config.xml.metadata, then D config.xml
|
||||
assert count == 3
|
||||
with output.open(encoding="utf-8", newline="") as handle:
|
||||
rows = list(csv.DictReader(handle))
|
||||
assert rows[0]["letter"] == "D" # newest collection first
|
||||
assert rows[0]["path"] == "config.xml"
|
||||
assert rows[1]["letter"] == "A"
|
||||
assert rows[1]["path"] == "config.xml"
|
||||
assert rows[1]["author"] == "DOMAIN\\jsmith"
|
||||
assert rows[1]["run_id"] # trailer parsed
|
||||
|
||||
def test_export_jsonl_and_since_filter(
|
||||
self, git_repo: Path, tracker_config: dict, tmp_path: Path
|
||||
) -> None:
|
||||
import json
|
||||
|
||||
from git_auto_tracker.config import AppConfig
|
||||
from git_auto_tracker.exporting.history import export_history
|
||||
|
||||
self._collect_two_cycles(git_repo, tracker_config, tmp_path)
|
||||
app_config = AppConfig.from_dict(tracker_config, config_dir=tmp_path)
|
||||
output = tmp_path / "history.jsonl"
|
||||
|
||||
# Future-dated --since excludes everything (2099, not 2999: Git's
|
||||
# approxidate parser mishandles far-future years and returns all)
|
||||
assert export_history(app_config, output, since="2099-01-01") == 0
|
||||
assert output.read_text(encoding="utf-8") == ""
|
||||
|
||||
# No filter: both collections' rows present, newest first
|
||||
assert export_history(app_config, output) == 3
|
||||
lines = output.read_text(encoding="utf-8").splitlines()
|
||||
parsed = [json.loads(line) for line in lines]
|
||||
assert parsed[0]["letter"] == "D"
|
||||
assert parsed[1]["letter"] == "A"
|
||||
assert parsed[0]["collected_at"] >= parsed[-1]["collected_at"]
|
||||
|
||||
def test_cli_export_command(
|
||||
self, git_repo: Path, tracker_config: dict, tmp_path: Path, capsys
|
||||
) -> None:
|
||||
from git_auto_tracker.cli import main
|
||||
|
||||
self._collect_two_cycles(git_repo, tracker_config, tmp_path)
|
||||
import yaml
|
||||
|
||||
config_path = tmp_path / "cfg.yaml"
|
||||
config_path.write_text(yaml.safe_dump(tracker_config), encoding="utf-8")
|
||||
output = tmp_path / "out.csv"
|
||||
|
||||
exit_code = main(["--config", str(config_path), "export", "-o", str(output)])
|
||||
assert exit_code == 0
|
||||
assert output.is_file()
|
||||
captured = capsys.readouterr().out
|
||||
assert "3 file-change record(s)" in captured
|
||||
|
||||
|
||||
class TestSafetyAborts:
|
||||
def test_pre_existing_staged_changes_abort(
|
||||
self, git_repo: Path, tracker_config: dict, tmp_path: Path
|
||||
|
||||
Reference in New Issue
Block a user