Write vs write_tree
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 2.1k
- Forks
- 450
- Avg merge
- 11m
- Merged PRs (30d)
- 1
Description
I am currently using git2 0.13.12.
If i read the documentation for write: https://docs.rs/git2/0.13.12/git2/struct.Index.html#method.write
Write an existing index object from memory back to disk using an atomic file lock.
and write_tree: https://docs.rs/git2/0.13.12/git2/struct.Index.html#method.write_tree
Write the index as a tree.
This method will scan the index and write a representation of its current state back to disk; it recursively creates tree objects for each of the subtrees stored in the index, but only returns the OID of the root tree. This is the OID that can be used e.g. to create a commit.
The index instance cannot be bare, and needs to be associated to an existing repository.
The index must not contain any file in conflict.
it sounds like i can just call write_tree, get the id and then commit. That is also how the init example explains it: https://github.com/rust-lang/git2-rs/blob/master/examples/init.rs:
/// Unlike regular "git init", this example shows how to create an initial empty
/// commit in the repository. This is the helper function that does that.
fn create_initial_commit(repo: &Repository) -> Result<(), Error> {
// First use the config to initialize a commit signature for the user.
let sig = repo.signature()?;
// Now let's create an empty tree for this commit
let tree_id = {
let mut index = repo.index()?;
// Outside of this example, you could call index.add_path()
// here to put actual files into the index. For our purposes, we'll
// leave it empty for now.
index.write_tree()?
};
let tree = repo.find_tree(tree_id)?;
// Ready to create the initial commit.
//
// Normally creating a commit would involve looking up the current HEAD
// commit and making that be the parent of the initial commit, but here this
// is the first commit so there will be no parent.
repo.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[])?;
Ok(())
}
But i find that this only work on initial commit.
I have this example
use git2::Commit;
use git2::ObjectType;
use git2::Repository;
use std::env;
use std::fs::File;
use std::path::Path;
fn find_last_commit(repo: &Repository) -> Result<Commit, git2::Error> {
let obj = repo.head()?.resolve()?.peel(ObjectType::Commit)?;
obj.into_commit()
.map_err(|_| git2::Error::from_str("Couldn't find commit"))
}
fn main() {
let args: Vec<String> = env::args().collect();
let root = &args[1];
let file_name = &args[2];
let repo = if Path::new(root).exists() {
println!("open");
Repository::open(root).unwrap()
} else {
println!("init");
Repository::init(root).unwrap()
};
let mut index = repo.index().unwrap();
File::create(Path::new(root).join(file_name)).unwrap();
index.add_path(Path::new(file_name)).unwrap();
index.write().unwrap();
let lc_result = find_last_commit(&repo);
let mut parent_commits: Vec<&Commit> = vec![];
match lc_result.as_ref() {
Ok(c) => parent_commits.push(c),
Err(_) => (),
};
let id = index.write_tree().unwrap();
let tree = repo.find_tree(id).unwrap();
repo.commit(
Some("HEAD"),
&repo.signature().unwrap(),
&repo.signature().unwrap(),
"commit message",
&tree,
&parent_commits,
)
.unwrap();
}
When i run it the first time
cargo run /path/to/testrepo file1.txt
It commits fine, but i need the write call
index.add_path(Path::new(file_name)).unwrap();
index.write().unwrap();
let lc_result = find_last_commit(&repo);
if i want call it again
cargo run /path/to/testrepo file2.txt
If i dont have the write call, it will just show file1.txt and file2.txt as deleted.
Do I need this write call in my example? Or am i using the library wrong? Or is this a bug? If i read the example init and the docs, it shouldn't be necessary to do the write, but my example wont work without.
I dont find it clear on how to use this correctly.
If i am using this correctly, it could be super awesome to have it stated more clearly in the docs or examples, that you need the write call.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by comparing the Index::write and Index::write_tree documentation with examples/init.rs and the provided two-run reproducer. Determine whether the example or API documentation needs clarification, then update the relevant documentation or example so the required index workflow and expected commit behavior are clear.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100