@@ -2069,6 +2069,55 @@ static int git_blame_config(const char *var, const char *value, void *cb)
2069
2069
return git_default_config (var , value , cb );
2070
2070
}
2071
2071
2072
+ static void verify_working_tree_path (struct commit * work_tree , const char * path )
2073
+ {
2074
+ struct commit_list * parents ;
2075
+
2076
+ for (parents = work_tree -> parents ; parents ; parents = parents -> next ) {
2077
+ const unsigned char * commit_sha1 = parents -> item -> object .sha1 ;
2078
+ unsigned char blob_sha1 [20 ];
2079
+ unsigned mode ;
2080
+
2081
+ if (!get_tree_entry (commit_sha1 , path , blob_sha1 , & mode ) &&
2082
+ sha1_object_info (blob_sha1 , NULL ) == OBJ_BLOB )
2083
+ return ;
2084
+ }
2085
+ die ("no such path '%s' in HEAD" , path );
2086
+ }
2087
+
2088
+ static struct commit_list * * append_parent (struct commit_list * * tail , const unsigned char * sha1 )
2089
+ {
2090
+ struct commit * parent ;
2091
+
2092
+ parent = lookup_commit_reference (sha1 );
2093
+ if (!parent )
2094
+ die ("no such commit %s" , sha1_to_hex (sha1 ));
2095
+ return & commit_list_insert (parent , tail )-> next ;
2096
+ }
2097
+
2098
+ static void append_merge_parents (struct commit_list * * tail )
2099
+ {
2100
+ int merge_head ;
2101
+ const char * merge_head_file = git_path ("MERGE_HEAD" );
2102
+ struct strbuf line = STRBUF_INIT ;
2103
+
2104
+ merge_head = open (merge_head_file , O_RDONLY );
2105
+ if (merge_head < 0 ) {
2106
+ if (errno == ENOENT )
2107
+ return ;
2108
+ die ("cannot open '%s' for reading" , merge_head_file );
2109
+ }
2110
+
2111
+ while (!strbuf_getwholeline_fd (& line , merge_head , '\n' )) {
2112
+ unsigned char sha1 [20 ];
2113
+ if (line .len < 40 || get_sha1_hex (line .buf , sha1 ))
2114
+ die ("unknown line in '%s': %s" , merge_head_file , line .buf );
2115
+ tail = append_parent (tail , sha1 );
2116
+ }
2117
+ close (merge_head );
2118
+ strbuf_release (& line );
2119
+ }
2120
+
2072
2121
/*
2073
2122
* Prepare a dummy commit that represents the work tree (or staged) item.
2074
2123
* Note that annotating work tree item never works in the reverse.
@@ -2079,27 +2128,46 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
2079
2128
{
2080
2129
struct commit * commit ;
2081
2130
struct origin * origin ;
2131
+ struct commit_list * * parent_tail , * parent ;
2082
2132
unsigned char head_sha1 [20 ];
2083
2133
struct strbuf buf = STRBUF_INIT ;
2084
2134
const char * ident ;
2085
2135
time_t now ;
2086
2136
int size , len ;
2087
2137
struct cache_entry * ce ;
2088
2138
unsigned mode ;
2089
-
2090
- if (get_sha1 ("HEAD" , head_sha1 ))
2091
- die ("No such ref: HEAD" );
2139
+ struct strbuf msg = STRBUF_INIT ;
2092
2140
2093
2141
time (& now );
2094
2142
commit = xcalloc (1 , sizeof (* commit ));
2095
- commit -> parents = xcalloc (1 , sizeof (* commit -> parents ));
2096
- commit -> parents -> item = lookup_commit_reference (head_sha1 );
2097
2143
commit -> object .parsed = 1 ;
2098
2144
commit -> date = now ;
2099
2145
commit -> object .type = OBJ_COMMIT ;
2146
+ parent_tail = & commit -> parents ;
2147
+
2148
+ if (!resolve_ref_unsafe ("HEAD" , head_sha1 , 1 , NULL ))
2149
+ die ("no such ref: HEAD" );
2150
+
2151
+ parent_tail = append_parent (parent_tail , head_sha1 );
2152
+ append_merge_parents (parent_tail );
2153
+ verify_working_tree_path (commit , path );
2100
2154
2101
2155
origin = make_origin (commit , path );
2102
2156
2157
+ ident = fmt_ident ("Not Committed Yet" , "not.committed.yet" , NULL , 0 );
2158
+ strbuf_addstr (& msg , "tree 0000000000000000000000000000000000000000\n" );
2159
+ for (parent = commit -> parents ; parent ; parent = parent -> next )
2160
+ strbuf_addf (& msg , "parent %s\n" ,
2161
+ sha1_to_hex (parent -> item -> object .sha1 ));
2162
+ strbuf_addf (& msg ,
2163
+ "author %s\n"
2164
+ "committer %s\n\n"
2165
+ "Version of %s from %s\n" ,
2166
+ ident , ident , path ,
2167
+ (!contents_from ? path :
2168
+ (!strcmp (contents_from , "-" ) ? "standard input" : contents_from )));
2169
+ commit -> buffer = strbuf_detach (& msg , NULL );
2170
+
2103
2171
if (!contents_from || strcmp ("-" , contents_from )) {
2104
2172
struct stat st ;
2105
2173
const char * read_from ;
@@ -2136,7 +2204,6 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
2136
2204
}
2137
2205
else {
2138
2206
/* Reading from stdin */
2139
- contents_from = "standard input" ;
2140
2207
mode = 0 ;
2141
2208
if (strbuf_read (& buf , 0 , 0 ) < 0 )
2142
2209
die_errno ("failed to read from stdin" );
@@ -2181,16 +2248,6 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
2181
2248
*/
2182
2249
cache_tree_invalidate_path (active_cache_tree , path );
2183
2250
2184
- commit -> buffer = xmalloc (400 );
2185
- ident = fmt_ident ("Not Committed Yet" , "not.committed.yet" , NULL , 0 );
2186
- snprintf (commit -> buffer , 400 ,
2187
- "tree 0000000000000000000000000000000000000000\n"
2188
- "parent %s\n"
2189
- "author %s\n"
2190
- "committer %s\n\n"
2191
- "Version of %s from %s\n" ,
2192
- sha1_to_hex (head_sha1 ),
2193
- ident , ident , path , contents_from ? contents_from : path );
2194
2251
return commit ;
2195
2252
}
2196
2253
0 commit comments