1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
//! Git tree building from index entries.
//!
//! This module handles converting a flat git index (list of files) into a
//! hierarchical git tree structure. This is one of the most complex parts of
//! the git data model.
//!
//! # Git Tree Structure
//!
//! Git stores directory hierarchies as tree objects. Each tree contains:
//! - Entries for files (blobs)
//! - Entries for subdirectories (subtrees)
//! - Entries for submodules (commits)
//!
//! ## Flat Index vs. Hierarchical Trees
//!
//! The index stores files as flat paths:
//! ```text
//! Cargo.toml
//! src/main.rs
//! src/lib.rs
//! tests/integration.rs
//! ```
//!
//! But git trees are hierarchical:
//! ```text
//! Root Tree
//! ├── Cargo.toml (blob)
//! ├── src/ (tree)
//! │ ├── main.rs (blob)
//! │ └── lib.rs (blob)
//! └── tests/ (tree)
//! └── integration.rs (blob)
//! ```
//!
//! # Tree Building Algorithm
//!
//! To convert index to trees:
//!
//! 1. **Group by Directory**: Split paths and group files by parent directory
//! 2. **Build Recursively**: Create trees from leaves up to root
//! 3. **Sort Entries**: Git requires lexicographic sorting
//! 4. **Write Objects**: Store each tree in the object database
//!
//! # Current Implementation
//!
//! The current implementation is **simplified** for the MVP:
//! - Only handles single-level trees (files in root directory)
//! - Files in subdirectories are flattened to root
//! - Full recursive tree building is TODO
//!
//! This works for most use cases where we're only bumping `Cargo.toml` in the
//! root directory.
//!
//! # Entry Modes
//!
//! Git supports several entry types:
//!
//! | Mode | Type | Description |
//! |------|------|-------------|
//! | 0100644 | Blob | Regular file |
//! | 0100755 | BlobExecutable | Executable file |
//! | 0120000 | Link | Symbolic link |
//! | 0040000 | Tree | Directory |
//! | 0160000 | Commit | Gitlink (submodule) |
//!
//! # Performance Considerations
//!
//! Tree building is I/O intensive:
//! - Each tree is a separate object in `.git/objects/`
//! - Large repositories with deep hierarchies create many tree objects
//! - The simplified implementation reduces this overhead
use ;
use ;
/// Build a git tree from index entries.
///
/// This function converts the flat list of files in the git index into a
/// hierarchical tree structure suitable for creating a commit.
///
/// # Current Limitation
///
/// **This is a simplified implementation** that only handles files in the root
/// directory. Files in subdirectories are currently included with their full
/// paths (e.g., "src/main.rs") rather than building proper subtrees.
///
/// For the bump command's use case (updating Cargo.toml), this limitation is
/// acceptable since Cargo.toml is always in the root directory.
///
/// # Arguments
///
/// * `index_state` - The index state containing file entries to build tree from
/// * `repo` - The git repository to write tree objects to
///
/// # Returns
///
/// Returns the object ID of the root tree.
///
/// # Errors
///
/// Returns an error if:
/// - Tree objects cannot be written to the object database
/// - Path conversions fail
/// - Invalid entry modes are encountered
///
/// # Examples
///
/// ```rust,no_run
/// # use anyhow::Result;
/// # use gix::index::State;
/// # fn example(repo: &gix::Repository, state: &State) -> Result<()> {
/// use cargo_version_info::commands::bump::tree::build_tree_from_index;
///
/// let tree_id = build_tree_from_index(state, repo)?;
/// println!("Created tree: {}", tree_id);
/// # Ok(())
/// # }
/// ```
///
/// # Algorithm
///
/// The current simplified algorithm:
///
/// 1. Iterate through all index entries
/// 2. Convert entry paths to tree entry format
/// 3. Convert entry modes to tree entry modes
/// 4. Sort entries by filename (git requirement)
/// 5. Build a single root tree with all entries
/// 6. Write the tree object to the repository
///
/// # Future Improvements
///
/// A full implementation would:
/// - Parse paths to identify directories
/// - Build trees recursively from leaves to root
/// - Handle deep directory structures
/// - Optimize by reusing unchanged subtrees
/// Convert index entry mode to tree entry mode.
///
/// The git index and git trees use different representations for file modes:
/// - Index uses `gix::index::entry::Mode` (bitflags)
/// - Trees use `gix::objs::tree::EntryMode` (wrapped u16)
///
/// # Supported Modes
///
/// - `FILE` (0100644): Regular file
/// - `FILE_EXECUTABLE` (0100755): Executable file
/// - `SYMLINK` (0120000): Symbolic link
/// - `DIR` (0040000): Directory/subdirectory
/// - `COMMIT` (0160000): Gitlink (submodule reference)
///
/// # Arguments
///
/// * `mode` - The index entry mode to convert
///
/// # Returns
///
/// Returns the equivalent tree entry mode.
///
/// # Examples
///
/// ```rust
/// # use gix::index::entry::Mode;
/// # use gix::objs::tree::EntryMode;
/// use cargo_version_info::commands::bump::tree::convert_mode_to_tree_mode;
///
/// let index_mode = Mode::FILE;
/// let tree_mode = convert_mode_to_tree_mode(index_mode);
/// // tree_mode is now EntryMode for a regular blob
/// ```