apply: add --intent-to-add
Similar to 'git reset -N', this option makes 'git apply' automatically mark new files as intent-to-add so they are visible in the following 'git diff' command and could also be committed with 'git commit -a'. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>maint
							parent
							
								
									8fc8f05cef
								
							
						
					
					
						commit
						cff5dc09ed
					
				|  | @ -9,7 +9,7 @@ git-apply - Apply a patch to files and/or to the index | ||||||
| SYNOPSIS | SYNOPSIS | ||||||
| -------- | -------- | ||||||
| [verse] | [verse] | ||||||
| 'git apply' [--stat] [--numstat] [--summary] [--check] [--index] [--3way] | 'git apply' [--stat] [--numstat] [--summary] [--check] [--index | --intent-to-add] [--3way] | ||||||
| 	  [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse] | 	  [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse] | ||||||
| 	  [--allow-binary-replacement | --binary] [--reject] [-z] | 	  [--allow-binary-replacement | --binary] [--reject] [-z] | ||||||
| 	  [-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached] | 	  [-p<n>] [-C<n>] [--inaccurate-eof] [--recount] [--cached] | ||||||
|  | @ -74,6 +74,14 @@ OPTIONS | ||||||
| 	cached data, apply the patch, and store the result in the index | 	cached data, apply the patch, and store the result in the index | ||||||
| 	without using the working tree. This implies `--index`. | 	without using the working tree. This implies `--index`. | ||||||
|  |  | ||||||
|  | --intent-to-add:: | ||||||
|  | 	When applying the patch only to the working tree, mark new | ||||||
|  | 	files to be added to the index later (see `--intent-to-add` | ||||||
|  | 	option in linkgit:git-add[1]). This option is ignored unless | ||||||
|  | 	running in a Git repository and `--index` is not specified. | ||||||
|  | 	Note that `--index` could be implied by other options such | ||||||
|  | 	as `--cached` or `--3way`. | ||||||
|  |  | ||||||
| -3:: | -3:: | ||||||
| --3way:: | --3way:: | ||||||
| 	When the patch does not apply cleanly, fall back on 3-way merge if | 	When the patch does not apply cleanly, fall back on 3-way merge if | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								apply.c
								
								
								
								
							
							
						
						
									
										19
									
								
								apply.c
								
								
								
								
							|  | @ -141,6 +141,8 @@ int check_apply_state(struct apply_state *state, int force_apply) | ||||||
| 			return error(_("--cached outside a repository")); | 			return error(_("--cached outside a repository")); | ||||||
| 		state->check_index = 1; | 		state->check_index = 1; | ||||||
| 	} | 	} | ||||||
|  | 	if (state->ita_only && (state->check_index || is_not_gitdir)) | ||||||
|  | 		state->ita_only = 0; | ||||||
| 	if (state->check_index) | 	if (state->check_index) | ||||||
| 		state->unsafe_paths = 0; | 		state->unsafe_paths = 0; | ||||||
|  |  | ||||||
|  | @ -4242,7 +4244,7 @@ static void patch_stats(struct apply_state *state, struct patch *patch) | ||||||
|  |  | ||||||
| static int remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty) | static int remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty) | ||||||
| { | { | ||||||
| 	if (state->update_index) { | 	if (state->update_index && !state->ita_only) { | ||||||
| 		if (remove_file_from_cache(patch->old_name) < 0) | 		if (remove_file_from_cache(patch->old_name) < 0) | ||||||
| 			return error(_("unable to remove %s from index"), patch->old_name); | 			return error(_("unable to remove %s from index"), patch->old_name); | ||||||
| 	} | 	} | ||||||
|  | @ -4265,15 +4267,15 @@ static int add_index_file(struct apply_state *state, | ||||||
| 	int namelen = strlen(path); | 	int namelen = strlen(path); | ||||||
| 	unsigned ce_size = cache_entry_size(namelen); | 	unsigned ce_size = cache_entry_size(namelen); | ||||||
|  |  | ||||||
| 	if (!state->update_index) |  | ||||||
| 		return 0; |  | ||||||
|  |  | ||||||
| 	ce = xcalloc(1, ce_size); | 	ce = xcalloc(1, ce_size); | ||||||
| 	memcpy(ce->name, path, namelen); | 	memcpy(ce->name, path, namelen); | ||||||
| 	ce->ce_mode = create_ce_mode(mode); | 	ce->ce_mode = create_ce_mode(mode); | ||||||
| 	ce->ce_flags = create_ce_flags(0); | 	ce->ce_flags = create_ce_flags(0); | ||||||
| 	ce->ce_namelen = namelen; | 	ce->ce_namelen = namelen; | ||||||
| 	if (S_ISGITLINK(mode)) { | 	if (state->ita_only) { | ||||||
|  | 		ce->ce_flags |= CE_INTENT_TO_ADD; | ||||||
|  | 		set_object_name_for_intent_to_add_entry(ce); | ||||||
|  | 	} else if (S_ISGITLINK(mode)) { | ||||||
| 		const char *s; | 		const char *s; | ||||||
|  |  | ||||||
| 		if (!skip_prefix(buf, "Subproject commit ", &s) || | 		if (!skip_prefix(buf, "Subproject commit ", &s) || | ||||||
|  | @ -4465,8 +4467,9 @@ static int create_file(struct apply_state *state, struct patch *patch) | ||||||
|  |  | ||||||
| 	if (patch->conflicted_threeway) | 	if (patch->conflicted_threeway) | ||||||
| 		return add_conflicted_stages_file(state, patch); | 		return add_conflicted_stages_file(state, patch); | ||||||
| 	else | 	else if (state->update_index) | ||||||
| 		return add_index_file(state, path, mode, buf, size); | 		return add_index_file(state, path, mode, buf, size); | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* phase zero is to remove, phase one is to create */ | /* phase zero is to remove, phase one is to create */ | ||||||
|  | @ -4686,7 +4689,7 @@ static int apply_patch(struct apply_state *state, | ||||||
| 	if (state->whitespace_error && (state->ws_error_action == die_on_ws_error)) | 	if (state->whitespace_error && (state->ws_error_action == die_on_ws_error)) | ||||||
| 		state->apply = 0; | 		state->apply = 0; | ||||||
|  |  | ||||||
| 	state->update_index = state->check_index && state->apply; | 	state->update_index = (state->check_index || state->ita_only) && state->apply; | ||||||
| 	if (state->update_index && !is_lock_file_locked(&state->lock_file)) { | 	if (state->update_index && !is_lock_file_locked(&state->lock_file)) { | ||||||
| 		if (state->index_file) | 		if (state->index_file) | ||||||
| 			hold_lock_file_for_update(&state->lock_file, | 			hold_lock_file_for_update(&state->lock_file, | ||||||
|  | @ -4941,6 +4944,8 @@ int apply_parse_options(int argc, const char **argv, | ||||||
| 			N_("instead of applying the patch, see if the patch is applicable")), | 			N_("instead of applying the patch, see if the patch is applicable")), | ||||||
| 		OPT_BOOL(0, "index", &state->check_index, | 		OPT_BOOL(0, "index", &state->check_index, | ||||||
| 			N_("make sure the patch is applicable to the current index")), | 			N_("make sure the patch is applicable to the current index")), | ||||||
|  | 		OPT_BOOL('N', "intent-to-add", &state->ita_only, | ||||||
|  | 			N_("mark new files with `git add --intent-to-add`")), | ||||||
| 		OPT_BOOL(0, "cached", &state->cached, | 		OPT_BOOL(0, "cached", &state->cached, | ||||||
| 			N_("apply a patch without touching the working tree")), | 			N_("apply a patch without touching the working tree")), | ||||||
| 		OPT_BOOL_F(0, "unsafe-paths", &state->unsafe_paths, | 		OPT_BOOL_F(0, "unsafe-paths", &state->unsafe_paths, | ||||||
|  |  | ||||||
							
								
								
									
										1
									
								
								apply.h
								
								
								
								
							
							
						
						
									
										1
									
								
								apply.h
								
								
								
								
							|  | @ -45,6 +45,7 @@ struct apply_state { | ||||||
| 	int check; /* preimage must match working tree, don't actually apply */ | 	int check; /* preimage must match working tree, don't actually apply */ | ||||||
| 	int check_index; /* preimage must match the indexed version */ | 	int check_index; /* preimage must match the indexed version */ | ||||||
| 	int update_index; /* check_index && apply */ | 	int update_index; /* check_index && apply */ | ||||||
|  | 	int ita_only;	  /* add intent-to-add entries to the index */ | ||||||
|  |  | ||||||
| 	/* These control cosmetic aspect of the output */ | 	/* These control cosmetic aspect of the output */ | ||||||
| 	int diffstat; /* just show a diffstat, and don't actually apply */ | 	int diffstat; /* just show a diffstat, and don't actually apply */ | ||||||
|  |  | ||||||
|  | @ -245,6 +245,7 @@ test_expect_success 'diff-files/diff-cached shows ita as new/not-new files' ' | ||||||
| 	test_cmp expected2 actual2 | 	test_cmp expected2 actual2 | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  |  | ||||||
| test_expect_success '"diff HEAD" includes ita as new files' ' | test_expect_success '"diff HEAD" includes ita as new files' ' | ||||||
| 	git reset --hard && | 	git reset --hard && | ||||||
| 	echo new >new-ita && | 	echo new >new-ita && | ||||||
|  | @ -262,4 +263,16 @@ test_expect_success '"diff HEAD" includes ita as new files' ' | ||||||
| 	test_cmp expected actual | 	test_cmp expected actual | ||||||
| ' | ' | ||||||
|  |  | ||||||
|  | test_expect_success 'apply --intent-to-add' ' | ||||||
|  | 	git reset --hard && | ||||||
|  | 	echo new >new-ita && | ||||||
|  | 	git add -N new-ita && | ||||||
|  | 	git diff >expected && | ||||||
|  | 	grep "new file" expected && | ||||||
|  | 	git reset --hard && | ||||||
|  | 	git apply --intent-to-add expected && | ||||||
|  | 	git diff >actual && | ||||||
|  | 	test_cmp expected actual | ||||||
|  | ' | ||||||
|  |  | ||||||
| test_done | test_done | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Nguyễn Thái Ngọc Duy
						Nguyễn Thái Ngọc Duy