44#include "git-compat-util.h"
55#include "add-patch.h"
66#include "advice.h"
7+ #include "commit.h"
78#include "config.h"
89#include "diff.h"
910#include "editor.h"
1011#include "environment.h"
1112#include "gettext.h"
13+ #include "hex.h"
1214#include "object-name.h"
1315#include "pager.h"
1416#include "read-cache-ll.h"
@@ -47,7 +49,7 @@ static struct patch_mode patch_mode_add = {
4749 N_ ("Stage mode change [y,n,q,a,d%s,?]? " ),
4850 N_ ("Stage deletion [y,n,q,a,d%s,?]? " ),
4951 N_ ("Stage addition [y,n,q,a,d%s,?]? " ),
50- N_ ("Stage this hunk [y,n,q,a,d%s,?]? " )
52+ N_ ("Stage this hunk [y,n,q,a,d%s,?]? " ),
5153 },
5254 .edit_hunk_hint = N_ ("If the patch applies cleanly, the edited hunk "
5355 "will immediately be marked for staging." ),
@@ -263,6 +265,8 @@ struct hunk {
263265
264266struct add_p_state {
265267 struct repository * r ;
268+ struct index_state * index ;
269+ const char * index_file ;
266270 struct interactive_config cfg ;
267271 struct strbuf answer , buf ;
268272
@@ -437,7 +441,7 @@ static void setup_child_process(struct add_p_state *s,
437441
438442 cp -> git_cmd = 1 ;
439443 strvec_pushf (& cp -> env ,
440- INDEX_ENVIRONMENT "=%s" , s -> r -> index_file );
444+ INDEX_ENVIRONMENT "=%s" , s -> index_file );
441445}
442446
443447static int parse_range (const char * * p ,
@@ -1903,7 +1907,7 @@ static int patch_update_file(struct add_p_state *s,
19031907 strbuf_reset (& s -> buf );
19041908 reassemble_patch (s , file_diff , 0 , & s -> buf );
19051909
1906- discard_index (s -> r -> index );
1910+ discard_index (s -> index );
19071911 if (s -> mode -> apply_for_checkout )
19081912 apply_for_checkout (s , & s -> buf ,
19091913 s -> mode -> is_reverse );
@@ -1914,9 +1918,11 @@ static int patch_update_file(struct add_p_state *s,
19141918 NULL , 0 , NULL , 0 ))
19151919 error (_ ("'git apply' failed" ));
19161920 }
1917- if (repo_read_index (s -> r ) >= 0 )
1921+ if (read_index_from (s -> index , s -> index_file , s -> r -> gitdir ) >= 0 &&
1922+ s -> index == s -> r -> index ) {
19181923 repo_refresh_and_write_index (s -> r , REFRESH_QUIET , 0 ,
19191924 1 , NULL , NULL , NULL );
1925+ }
19201926 }
19211927
19221928 putchar ('\n' );
@@ -1929,6 +1935,8 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
19291935{
19301936 struct add_p_state s = {
19311937 .r = r ,
1938+ .index = r -> index ,
1939+ .index_file = r -> index_file ,
19321940 .answer = STRBUF_INIT ,
19331941 .buf = STRBUF_INIT ,
19341942 .plain = STRBUF_INIT ,
@@ -1987,3 +1995,99 @@ int run_add_p(struct repository *r, enum add_p_mode mode,
19871995 add_p_state_clear (& s );
19881996 return 0 ;
19891997}
1998+
1999+ int run_add_p_index (struct repository * r ,
2000+ struct index_state * index ,
2001+ const char * index_file ,
2002+ struct interactive_options * opts ,
2003+ const char * revision ,
2004+ const struct pathspec * ps )
2005+ {
2006+ struct patch_mode mode = {
2007+ .apply_args = { "--cached" , NULL },
2008+ .apply_check_args = { "--cached" , NULL },
2009+ .prompt_mode = {
2010+ N_ ("Stage mode change [y,n,q,a,d%s,?]? " ),
2011+ N_ ("Stage deletion [y,n,q,a,d%s,?]? " ),
2012+ N_ ("Stage addition [y,n,q,a,d%s,?]? " ),
2013+ N_ ("Stage this hunk [y,n,q,a,d%s,?]? " )
2014+ },
2015+ .edit_hunk_hint = N_ ("If the patch applies cleanly, the edited hunk "
2016+ "will immediately be marked for staging." ),
2017+ .help_patch_text =
2018+ N_ ("y - stage this hunk\n"
2019+ "n - do not stage this hunk\n"
2020+ "q - quit; do not stage this hunk or any of the remaining "
2021+ "ones\n"
2022+ "a - stage this hunk and all later hunks in the file\n"
2023+ "d - do not stage this hunk or any of the later hunks in "
2024+ "the file\n" ),
2025+ .index_only = 1 ,
2026+ };
2027+ struct add_p_state s = {
2028+ .r = r ,
2029+ .index = index ,
2030+ .index_file = index_file ,
2031+ .answer = STRBUF_INIT ,
2032+ .buf = STRBUF_INIT ,
2033+ .plain = STRBUF_INIT ,
2034+ .colored = STRBUF_INIT ,
2035+ .mode = & mode ,
2036+ .revision = revision ,
2037+ };
2038+ struct strbuf parent_revision = STRBUF_INIT ;
2039+ char parent_tree_oid [GIT_MAX_HEXSZ + 1 ];
2040+ size_t binary_count = 0 ;
2041+ struct commit * commit ;
2042+ int ret ;
2043+
2044+ commit = lookup_commit_reference_by_name (revision );
2045+ if (!commit ) {
2046+ err (& s , _ ("Revision does not refer to a commit" ));
2047+ ret = -1 ;
2048+ goto out ;
2049+ }
2050+
2051+ if (commit -> parents )
2052+ oid_to_hex_r (parent_tree_oid , get_commit_tree_oid (commit -> parents -> item ));
2053+ else
2054+ oid_to_hex_r (parent_tree_oid , r -> hash_algo -> empty_tree );
2055+
2056+ strbuf_addf (& parent_revision , "%s~" , revision );
2057+ mode .diff_cmd [0 ] = "diff-tree" ;
2058+ mode .diff_cmd [1 ] = "-r" ;
2059+ mode .diff_cmd [2 ] = parent_tree_oid ;
2060+
2061+ interactive_config_init (& s .cfg , r , opts );
2062+
2063+ if (parse_diff (& s , ps ) < 0 ) {
2064+ ret = -1 ;
2065+ goto out ;
2066+ }
2067+
2068+ for (size_t i = 0 ; i < s .file_diff_nr ; i ++ ) {
2069+ if (s .file_diff [i ].binary && !s .file_diff [i ].hunk_nr )
2070+ binary_count ++ ;
2071+ else if (patch_update_file (& s , s .file_diff + i ))
2072+ break ;
2073+ }
2074+
2075+ if (s .file_diff_nr == 0 ) {
2076+ err (& s , _ ("No changes." ));
2077+ ret = -1 ;
2078+ goto out ;
2079+ }
2080+
2081+ if (binary_count == s .file_diff_nr ) {
2082+ err (& s , _ ("Only binary files changed." ));
2083+ ret = -1 ;
2084+ goto out ;
2085+ }
2086+
2087+ ret = 0 ;
2088+
2089+ out :
2090+ strbuf_release (& parent_revision );
2091+ add_p_state_clear (& s );
2092+ return ret ;
2093+ }
0 commit comments