Skip to content
Merged
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
23 changes: 20 additions & 3 deletions minigit/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,21 @@ def _working_status(self) -> DiffResult:

return result

def checkout(self, tree_hash) -> None:
def checkout(self, tree_hash, conflicted_paths=()) -> None:
"""Make the working files and the index match `tree_hash`.

`conflicted_paths` (used by a merge) are written to disk like every other
path - their blob in the tree holds the conflict markers - but their index
entry stays at its pre-merge version (or is left out if there was none), so
status reports them as "not staged" until `add` resolves them.
"""
target_entries = self.read_tree_entries(tree_hash)
target_by_path = {e.path: e for e in target_entries}

conflicted = set(conflicted_paths)
for path in sorted(conflicted - set(target_by_path)):
raise MiniGitError(f"conflicted path is not in the target tree: {path}")

# Reject unsafe paths
blob_cache = {}
for entry in target_entries:
Expand Down Expand Up @@ -451,8 +462,14 @@ def checkout(self, tree_hash) -> None:
f.write(blob_cache[entry.path])
os.chmod(full_path, 0o755 if entry.mode == "100755" else 0o644)

# Now matched
self.write_index(target_entries)
# Now matched - except conflicted paths, which keep their pre-merge entry.
index_entries = []
for entry in target_entries:
if entry.path not in conflicted:
index_entries.append(entry)
elif entry.path in current_by_path:
index_entries.append(current_by_path[entry.path])
self.write_index(index_entries)

def _validate_checkout_path(self, path: str) -> None:
if (
Expand Down
Loading
Loading