Implement Deterministic Merkle Hashing for a Repository
Company: Cursor
Role: Software Engineer
Category: Software Engineering Fundamentals
Difficulty: medium
Interview Round: Technical Screen
# Implement Deterministic Merkle Hashing for a Repository
You are given a repository abstraction with operations to identify files and directories, read a file's bytes, and list a directory's immediate children by name. Design and implement a `MerkleTree` API with:
```python
def get_hash(path: str) -> str:
...
```
The hash for a file must depend on its bytes. The hash for a directory must depend on every descendant's name, type, and hash, but not on the order returned by the repository API. State a deterministic serialization and cryptographic hash choice. Explain caching and invalidation if repository contents can change.
### Constraints & Assumptions
- File contents are arbitrary bytes and may be large.
- File and directory namespaces can contain similar names; ambiguous concatenation is not acceptable.
- Directory enumeration order is unspecified.
- Clarify treatment of symbolic links, permissions, ignored files, and concurrent modification before including them in the contract.
### Clarifying Questions to Ask
- Is the repository an immutable snapshot while one root hash is computed?
- Should metadata such as executable bits affect identity?
- Are symbolic links hashed as links, followed, or rejected?
- Is `get_hash` called mainly for roots, arbitrary subpaths, or repeated incremental updates?
### What a Strong Answer Covers
- Domain separation and unambiguous encoding for files and directories
- Stable child ordering and inclusion of child names and types
- Streaming file hashing, error propagation, and cycle handling
- Cache keys tied to repository version or sound invalidation
- Tests proving determinism and sensitivity to meaningful changes
### Follow-up Questions
- How can two repositories compare efficiently once root hashes differ?
- What race occurs if a file changes during traversal?
- How would you update hashes after one leaf changes?
- Why is concatenating raw child hashes insufficient?
Quick Answer: Implement deterministic Merkle hashing for files and directories in a repository abstraction. Define stable serialization, child ordering, streaming file hashes, metadata and symlink policy, cache invalidation, and behavior during concurrent changes.