Skip to content

Commit d8d3825

Browse files
knewtalexcrichton
authored andcommitted
Add binding for index_add_frombuffer (already existed in libgit2-sys) (rust-lang#344)
1 parent ef9c8ed commit d8d3825

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

src/index.rs

+76
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,66 @@ impl Index {
127127
}
128128
}
129129

130+
/// Add or update an index entry from a buffer in memory
131+
///
132+
/// This method will create a blob in the repository that owns the index and
133+
/// then add the index entry to the index. The path of the entry represents
134+
/// the position of the blob relative to the repository's root folder.
135+
///
136+
/// If a previous index entry exists that has the same path as the given
137+
/// 'entry', it will be replaced. Otherwise, the 'entry' will be added.
138+
/// The id and the file_size of the 'entry' are updated with the real value
139+
/// of the blob.
140+
///
141+
/// This forces the file to be added to the index, not looking at gitignore
142+
/// rules.
143+
///
144+
/// If this file currently is the result of a merge conflict, this file will
145+
/// no longer be marked as conflicting. The data about the conflict will be
146+
/// moved to the "resolve undo" (REUC) section.
147+
pub fn add_frombuffer(&mut self, entry: &IndexEntry, data: &[u8]) -> Result<(), Error> {
148+
let path = try!(CString::new(&entry.path[..]));
149+
150+
// libgit2 encodes the length of the path in the lower bits of the
151+
// `flags` entry, so mask those out and recalculate here to ensure we
152+
// don't corrupt anything.
153+
let mut flags = entry.flags & !raw::GIT_IDXENTRY_NAMEMASK;
154+
155+
if entry.path.len() < raw::GIT_IDXENTRY_NAMEMASK as usize {
156+
flags |= entry.path.len() as u16;
157+
} else {
158+
flags |= raw::GIT_IDXENTRY_NAMEMASK;
159+
}
160+
161+
unsafe {
162+
let raw = raw::git_index_entry {
163+
dev: entry.dev,
164+
ino: entry.ino,
165+
mode: entry.mode,
166+
uid: entry.uid,
167+
gid: entry.gid,
168+
file_size: entry.file_size,
169+
id: *entry.id.raw(),
170+
flags: flags,
171+
flags_extended: entry.flags_extended,
172+
path: path.as_ptr(),
173+
mtime: raw::git_index_time {
174+
seconds: entry.mtime.seconds(),
175+
nanoseconds: entry.mtime.nanoseconds(),
176+
},
177+
ctime: raw::git_index_time {
178+
seconds: entry.ctime.seconds(),
179+
nanoseconds: entry.ctime.nanoseconds(),
180+
},
181+
};
182+
183+
let ptr = data.as_ptr() as *const c_void;
184+
let len = data.len() as size_t;
185+
try_call!(raw::git_index_add_frombuffer(self.raw, &raw, ptr, len));
186+
Ok(())
187+
}
188+
}
189+
130190
/// Add or update an index entry from a file on disk
131191
///
132192
/// The file path must be relative to the repository's working folder and
@@ -615,6 +675,22 @@ mod tests {
615675
assert_eq!(e.path.len(), 6);
616676
}
617677

678+
#[test]
679+
fn add_frombuffer_then_read() {
680+
let (_td, repo) = ::test::repo_init();
681+
let mut index = repo.index().unwrap();
682+
683+
let mut e = entry();
684+
e.path = b"foobar".to_vec();
685+
let content = b"the contents";
686+
index.add_frombuffer(&e, content).unwrap();
687+
let e = index.get(0).unwrap();
688+
assert_eq!(e.path.len(), 6);
689+
690+
let b = repo.find_blob(e.id).unwrap();
691+
assert_eq!(b.content(), content);
692+
}
693+
618694
fn entry() -> IndexEntry {
619695
IndexEntry {
620696
ctime: IndexTime::new(0, 0),

0 commit comments

Comments
 (0)