FileTree Struct in Dive: How Container Filesystems Are Modeled and Analyzed
The FileTree struct in Dive is the core in-memory representation of a container image's filesystem hierarchy, storing the root node, visible node count, total file size, and metadata required to render ASCII trees and compute layer diffs.
The FileTree struct serves as the foundational data structure in the wagoodman/dive source code that enables deep analysis of Docker and OCI container images. Defined in dive/filetree/file_tree.go, this struct models the complete set of files, directories, and their relationships within a single image layer or an entire image filesystem, powering Dive's terminal UI and efficient diff calculations.
What Is the FileTree Struct in Dive?
The FileTree struct acts as the primary in-memory model that captures the hierarchy of files and directories existing inside a container image or a single image layer. It abstracts complex filesystem metadata into a traversable tree structure that Dive uses to visualize layer contents, calculate space utilization, and identify changes between image layers.
Core Purpose and Capabilities
According to the Dive source code, the FileTree struct enables three critical functions:
- Filesystem Modeling: Stores the complete directory structure and file metadata for a given layer, including paths, sizes, and permissions
- Diff Computation: Compares two
FileTreeinstances to identify added, removed, or modified files between layers using theCompareAndMarkmethod - UI Rendering: Generates ASCII tree visualizations showing file paths, sizes, and change markers in the terminal interface via the
Stringmethod
FileTree Struct Definition and Fields
The struct definition resides in dive/filetree/file_tree.go at lines 24-32:
// FileTree represents a set of files, directories, and their relations.
type FileTree struct {
Root *FileNode // top‑level node (virtual root)
Size int // number of visible nodes (excluding root)
FileSize uint64 // total byte size of all files in the tree
Name string // optional name/label for the tree (e.g., layer digest)
Id uuid.UUID // unique identifier for the tree instance
SortOrder SortOrder // how children are ordered when traversed/rendered
}
Each field serves a specific purpose in the container image analysis workflow:
Root(*FileNode): Anchors the entire tree structure with a virtual root node that contains all top-level directories and files as defined indive/filetree/file_node.goSize(int): Tracks the count of visible nodes excluding the artificial root, used for UI statistics and paginationFileSize(uint64): Accumulates the total byte size of all files in the tree, enabling accurate layer size calculations and space analysisName(string): Provides a human-readable identifier, typically populated with the layer digest or image reference for debuggingId(uuid.UUID): Assigns a unique identifier to each tree instance for cache management and comparison operationsSortOrder(SortOrder): Defines the traversal strategy (by name, size, etc.) used when rendering the tree in the terminal UI
Working with the FileTree Struct in Go
The dive/filetree package provides methods to construct, manipulate, and compare FileTree instances. These operations form the backbone of Dive's image analysis capabilities.
1. Creating a New FileTree
Initialize an empty tree and assign identifying metadata:
tree := filetree.NewFileTree()
tree.Name = "layer-1"
2. Adding File Paths
Populate the tree with file metadata using absolute paths:
info := filetree.FileInfo{
Path: "usr/bin/app",
Size: 123456,
Mode: 0755,
IsDir: false,
}
node, _, err := tree.AddPath("/usr/bin/app", info)
if err != nil {
// handle error
}
3. Retrieving Nodes
Access specific files or directories by their absolute path:
node, err := tree.GetNode("/usr/bin/app")
if err != nil {
// not found
}
fmt.Println("File size:", node.Data.FileInfo.Size)
4. Rendering the ASCII Tree
Generate human-readable output for the terminal UI:
fmt.Println(tree.String(true)) // `true` adds file attributes (size, mode, etc.)
5. Comparing Trees for Layer Diffs
Compute differences between two FileTree instances to identify filesystem changes:
lower := filetree.NewFileTree()
// …populate lower…
upper := filetree.NewFileTree()
// …populate upper…
if _, err := lower.CompareAndMark(upper); err != nil {
// diff annotations (Added, Removed, Modified) are now attached to nodes
}
The CompareAndMark method, as implemented in dive/filetree/file_tree.go, traverses both trees simultaneously and annotates nodes with change types that the UI renders as color-coded indicators.
Key Source Files in the FileTree Architecture
Understanding the FileTree struct requires familiarity with several interconnected components in the wagoodman/dive repository:
dive/filetree/file_tree.go: Contains theFileTreestruct definition and core operations includingNewFileTree,AddPath,GetNode,CompareAndMark, and tree traversal logicdive/filetree/file_node.go: DefinesFileNode, the individual file/directory representation that comprises the tree nodes, along with rendering helpers for the ASCII outputdive/filetree/file_tree_test.go: Provides unit tests exercising tree creation, manipulation, copying, and edge cases to ensure correctnesscmd/dive/cli/internal/ui/v1/viewmodel/filetree.go: Implements the UI view-model that wrapsFileTreefor the right-pane display in the terminal interfacedive/filetree/comparer.go: Houses higher-level diff logic that orchestratesFileTree.CompareAndMarkto produce comprehensive layer comparisons
These components work together to model, analyze, and visualize the filesystem structure of Docker and OCI images layer by layer.
Summary
- The
FileTreestruct indive/filetree/file_tree.gois the central data structure for modeling container image filesystems in Dive - It tracks the root node, visible node count, total file size, and traversal ordering via the
Root,Size,FileSize, andSortOrderfields - The struct supports filesystem construction through
AddPath, node retrieval viaGetNode, and ASCII rendering withString() - Layer diffs are computed using
CompareAndMark, which annotates nodes with change states (Added, Removed, Modified) - The architecture separates tree logic (
file_tree.go), node representation (file_node.go), UI presentation (viewmodel/filetree.go), and comparison orchestration (comparer.go)
Frequently Asked Questions
What does the FileTree struct represent in Dive?
The FileTree struct represents the complete hierarchy of files and directories within a container image layer or an entire image filesystem. It serves as the in-memory model that Dive uses to track file metadata, compute space utilization, and render the ASCII tree view in the terminal UI.
Where is the FileTree struct defined in the Dive source code?
The FileTree struct is defined in dive/filetree/file_tree.go at lines 24-32. This file also contains the primary methods for tree manipulation including NewFileTree, AddPath, GetNode, CompareAndMark, and the String method for ASCII rendering.
How does Dive use the FileTree struct to show layer differences?
Dive uses the CompareAndMark method to compare two FileTree instances representing different layers. This method traverses both trees simultaneously, identifying nodes that exist only in the upper tree (Added), only in the lower tree (Removed), or with differing metadata (Modified). These annotations are then rendered as color-coded indicators in the terminal UI by the view-model in cmd/dive/cli/internal/ui/v1/viewmodel/filetree.go.
What is the difference between FileTree and FileNode in Dive?
FileTree is the container struct that holds the entire filesystem model including the root node and aggregate statistics like total size. FileNode, defined in dive/filetree/file_node.go, represents individual files or directories within that tree. Each FileTree has a Root field pointing to a FileNode, which then links to child nodes via pointer relationships to form the complete directory hierarchy.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →