@@ -127,6 +127,66 @@ impl Index {
127
127
}
128
128
}
129
129
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
+
130
190
/// Add or update an index entry from a file on disk
131
191
///
132
192
/// The file path must be relative to the repository's working folder and
@@ -615,6 +675,22 @@ mod tests {
615
675
assert_eq ! ( e. path. len( ) , 6 ) ;
616
676
}
617
677
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
+
618
694
fn entry ( ) -> IndexEntry {
619
695
IndexEntry {
620
696
ctime : IndexTime :: new ( 0 , 0 ) ,
0 commit comments