Move try_merge_command and checkout_fast_forward to libgit.a
These functions are called in sequencer.c, which is part of libgit.a. This makes libgit.a potentially require builtin/merge.c for external git commands. Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Jeff King <peff@peff.net>maint
							parent
							
								
									2cfceefaca
								
							
						
					
					
						commit
						db699a8a1f
					
				
							
								
								
									
										1
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										1
									
								
								Makefile
								
								
								
								
							|  | @ -763,6 +763,7 @@ LIB_OBJS += lockfile.o | ||||||
| LIB_OBJS += log-tree.o | LIB_OBJS += log-tree.o | ||||||
| LIB_OBJS += mailmap.o | LIB_OBJS += mailmap.o | ||||||
| LIB_OBJS += match-trees.o | LIB_OBJS += match-trees.o | ||||||
|  | LIB_OBJS += merge.o | ||||||
| LIB_OBJS += merge-file.o | LIB_OBJS += merge-file.o | ||||||
| LIB_OBJS += merge-recursive.o | LIB_OBJS += merge-recursive.o | ||||||
| LIB_OBJS += mergesort.o | LIB_OBJS += mergesort.o | ||||||
|  |  | ||||||
							
								
								
									
										106
									
								
								builtin/merge.c
								
								
								
								
							
							
						
						
									
										106
									
								
								builtin/merge.c
								
								
								
								
							|  | @ -628,59 +628,6 @@ static void write_tree_trivial(unsigned char *sha1) | ||||||
| 		die(_("git write-tree failed to write a tree")); | 		die(_("git write-tree failed to write a tree")); | ||||||
| } | } | ||||||
|  |  | ||||||
| static const char *merge_argument(struct commit *commit) |  | ||||||
| { |  | ||||||
| 	if (commit) |  | ||||||
| 		return sha1_to_hex(commit->object.sha1); |  | ||||||
| 	else |  | ||||||
| 		return EMPTY_TREE_SHA1_HEX; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int try_merge_command(const char *strategy, size_t xopts_nr, |  | ||||||
| 		      const char **xopts, struct commit_list *common, |  | ||||||
| 		      const char *head_arg, struct commit_list *remotes) |  | ||||||
| { |  | ||||||
| 	const char **args; |  | ||||||
| 	int i = 0, x = 0, ret; |  | ||||||
| 	struct commit_list *j; |  | ||||||
| 	struct strbuf buf = STRBUF_INIT; |  | ||||||
|  |  | ||||||
| 	args = xmalloc((4 + xopts_nr + commit_list_count(common) + |  | ||||||
| 			commit_list_count(remotes)) * sizeof(char *)); |  | ||||||
| 	strbuf_addf(&buf, "merge-%s", strategy); |  | ||||||
| 	args[i++] = buf.buf; |  | ||||||
| 	for (x = 0; x < xopts_nr; x++) { |  | ||||||
| 		char *s = xmalloc(strlen(xopts[x])+2+1); |  | ||||||
| 		strcpy(s, "--"); |  | ||||||
| 		strcpy(s+2, xopts[x]); |  | ||||||
| 		args[i++] = s; |  | ||||||
| 	} |  | ||||||
| 	for (j = common; j; j = j->next) |  | ||||||
| 		args[i++] = xstrdup(merge_argument(j->item)); |  | ||||||
| 	args[i++] = "--"; |  | ||||||
| 	args[i++] = head_arg; |  | ||||||
| 	for (j = remotes; j; j = j->next) |  | ||||||
| 		args[i++] = xstrdup(merge_argument(j->item)); |  | ||||||
| 	args[i] = NULL; |  | ||||||
| 	ret = run_command_v_opt(args, RUN_GIT_CMD); |  | ||||||
| 	strbuf_release(&buf); |  | ||||||
| 	i = 1; |  | ||||||
| 	for (x = 0; x < xopts_nr; x++) |  | ||||||
| 		free((void *)args[i++]); |  | ||||||
| 	for (j = common; j; j = j->next) |  | ||||||
| 		free((void *)args[i++]); |  | ||||||
| 	i += 2; |  | ||||||
| 	for (j = remotes; j; j = j->next) |  | ||||||
| 		free((void *)args[i++]); |  | ||||||
| 	free(args); |  | ||||||
| 	discard_cache(); |  | ||||||
| 	if (read_cache() < 0) |  | ||||||
| 		die(_("failed to read the cache")); |  | ||||||
| 	resolve_undo_clear(); |  | ||||||
|  |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int try_merge_strategy(const char *strategy, struct commit_list *common, | static int try_merge_strategy(const char *strategy, struct commit_list *common, | ||||||
| 			      struct commit_list *remoteheads, | 			      struct commit_list *remoteheads, | ||||||
| 			      struct commit *head, const char *head_arg) | 			      struct commit *head, const char *head_arg) | ||||||
|  | @ -762,56 +709,6 @@ static int count_unmerged_entries(void) | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int checkout_fast_forward(const unsigned char *head, const unsigned char *remote) |  | ||||||
| { |  | ||||||
| 	struct tree *trees[MAX_UNPACK_TREES]; |  | ||||||
| 	struct unpack_trees_options opts; |  | ||||||
| 	struct tree_desc t[MAX_UNPACK_TREES]; |  | ||||||
| 	int i, fd, nr_trees = 0; |  | ||||||
| 	struct dir_struct dir; |  | ||||||
| 	struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file)); |  | ||||||
|  |  | ||||||
| 	refresh_cache(REFRESH_QUIET); |  | ||||||
|  |  | ||||||
| 	fd = hold_locked_index(lock_file, 1); |  | ||||||
|  |  | ||||||
| 	memset(&trees, 0, sizeof(trees)); |  | ||||||
| 	memset(&opts, 0, sizeof(opts)); |  | ||||||
| 	memset(&t, 0, sizeof(t)); |  | ||||||
| 	if (overwrite_ignore) { |  | ||||||
| 		memset(&dir, 0, sizeof(dir)); |  | ||||||
| 		dir.flags |= DIR_SHOW_IGNORED; |  | ||||||
| 		setup_standard_excludes(&dir); |  | ||||||
| 		opts.dir = &dir; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	opts.head_idx = 1; |  | ||||||
| 	opts.src_index = &the_index; |  | ||||||
| 	opts.dst_index = &the_index; |  | ||||||
| 	opts.update = 1; |  | ||||||
| 	opts.verbose_update = 1; |  | ||||||
| 	opts.merge = 1; |  | ||||||
| 	opts.fn = twoway_merge; |  | ||||||
| 	setup_unpack_trees_porcelain(&opts, "merge"); |  | ||||||
|  |  | ||||||
| 	trees[nr_trees] = parse_tree_indirect(head); |  | ||||||
| 	if (!trees[nr_trees++]) |  | ||||||
| 		return -1; |  | ||||||
| 	trees[nr_trees] = parse_tree_indirect(remote); |  | ||||||
| 	if (!trees[nr_trees++]) |  | ||||||
| 		return -1; |  | ||||||
| 	for (i = 0; i < nr_trees; i++) { |  | ||||||
| 		parse_tree(trees[i]); |  | ||||||
| 		init_tree_desc(t+i, trees[i]->buffer, trees[i]->size); |  | ||||||
| 	} |  | ||||||
| 	if (unpack_trees(nr_trees, t, &opts)) |  | ||||||
| 		return -1; |  | ||||||
| 	if (write_cache(fd, active_cache, active_nr) || |  | ||||||
| 		commit_locked_index(lock_file)) |  | ||||||
| 		die(_("unable to write new index file")); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void split_merge_strategies(const char *string, struct strategy **list, | static void split_merge_strategies(const char *string, struct strategy **list, | ||||||
| 				   int *nr, int *alloc) | 				   int *nr, int *alloc) | ||||||
| { | { | ||||||
|  | @ -1424,7 +1321,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (checkout_fast_forward(head_commit->object.sha1, | 		if (checkout_fast_forward(head_commit->object.sha1, | ||||||
| 					  commit->object.sha1)) { | 					  commit->object.sha1, | ||||||
|  | 					  overwrite_ignore)) { | ||||||
| 			ret = 1; | 			ret = 1; | ||||||
| 			goto done; | 			goto done; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										11
									
								
								cache.h
								
								
								
								
							|  | @ -1265,8 +1265,15 @@ struct startup_info { | ||||||
| }; | }; | ||||||
| extern struct startup_info *startup_info; | extern struct startup_info *startup_info; | ||||||
|  |  | ||||||
| /* builtin/merge.c */ | /* merge.c */ | ||||||
| int checkout_fast_forward(const unsigned char *from, const unsigned char *to); | struct commit_list; | ||||||
|  | int try_merge_command(const char *strategy, size_t xopts_nr, | ||||||
|  | 		const char **xopts, struct commit_list *common, | ||||||
|  | 		const char *head_arg, struct commit_list *remotes); | ||||||
|  | int checkout_fast_forward(const unsigned char *from, | ||||||
|  | 			  const unsigned char *to, | ||||||
|  | 			  int overwrite_ignore); | ||||||
|  |  | ||||||
|  |  | ||||||
| int sane_execvp(const char *file, char *const argv[]); | int sane_execvp(const char *file, char *const argv[]); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ -59,9 +59,4 @@ struct tree *write_tree_from_memory(struct merge_options *o); | ||||||
|  |  | ||||||
| int parse_merge_opt(struct merge_options *out, const char *s); | int parse_merge_opt(struct merge_options *out, const char *s); | ||||||
|  |  | ||||||
| /* builtin/merge.c */ |  | ||||||
| int try_merge_command(const char *strategy, size_t xopts_nr, |  | ||||||
| 		const char **xopts, struct commit_list *common, |  | ||||||
| 		const char *head_arg, struct commit_list *remotes); |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -0,0 +1,112 @@ | ||||||
|  | #include "cache.h" | ||||||
|  | #include "commit.h" | ||||||
|  | #include "run-command.h" | ||||||
|  | #include "resolve-undo.h" | ||||||
|  | #include "tree-walk.h" | ||||||
|  | #include "unpack-trees.h" | ||||||
|  | #include "dir.h" | ||||||
|  |  | ||||||
|  | static const char *merge_argument(struct commit *commit) | ||||||
|  | { | ||||||
|  | 	if (commit) | ||||||
|  | 		return sha1_to_hex(commit->object.sha1); | ||||||
|  | 	else | ||||||
|  | 		return EMPTY_TREE_SHA1_HEX; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int try_merge_command(const char *strategy, size_t xopts_nr, | ||||||
|  | 		      const char **xopts, struct commit_list *common, | ||||||
|  | 		      const char *head_arg, struct commit_list *remotes) | ||||||
|  | { | ||||||
|  | 	const char **args; | ||||||
|  | 	int i = 0, x = 0, ret; | ||||||
|  | 	struct commit_list *j; | ||||||
|  | 	struct strbuf buf = STRBUF_INIT; | ||||||
|  |  | ||||||
|  | 	args = xmalloc((4 + xopts_nr + commit_list_count(common) + | ||||||
|  | 			commit_list_count(remotes)) * sizeof(char *)); | ||||||
|  | 	strbuf_addf(&buf, "merge-%s", strategy); | ||||||
|  | 	args[i++] = buf.buf; | ||||||
|  | 	for (x = 0; x < xopts_nr; x++) { | ||||||
|  | 		char *s = xmalloc(strlen(xopts[x])+2+1); | ||||||
|  | 		strcpy(s, "--"); | ||||||
|  | 		strcpy(s+2, xopts[x]); | ||||||
|  | 		args[i++] = s; | ||||||
|  | 	} | ||||||
|  | 	for (j = common; j; j = j->next) | ||||||
|  | 		args[i++] = xstrdup(merge_argument(j->item)); | ||||||
|  | 	args[i++] = "--"; | ||||||
|  | 	args[i++] = head_arg; | ||||||
|  | 	for (j = remotes; j; j = j->next) | ||||||
|  | 		args[i++] = xstrdup(merge_argument(j->item)); | ||||||
|  | 	args[i] = NULL; | ||||||
|  | 	ret = run_command_v_opt(args, RUN_GIT_CMD); | ||||||
|  | 	strbuf_release(&buf); | ||||||
|  | 	i = 1; | ||||||
|  | 	for (x = 0; x < xopts_nr; x++) | ||||||
|  | 		free((void *)args[i++]); | ||||||
|  | 	for (j = common; j; j = j->next) | ||||||
|  | 		free((void *)args[i++]); | ||||||
|  | 	i += 2; | ||||||
|  | 	for (j = remotes; j; j = j->next) | ||||||
|  | 		free((void *)args[i++]); | ||||||
|  | 	free(args); | ||||||
|  | 	discard_cache(); | ||||||
|  | 	if (read_cache() < 0) | ||||||
|  | 		die(_("failed to read the cache")); | ||||||
|  | 	resolve_undo_clear(); | ||||||
|  |  | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int checkout_fast_forward(const unsigned char *head, | ||||||
|  | 			  const unsigned char *remote, | ||||||
|  | 			  int overwrite_ignore) | ||||||
|  | { | ||||||
|  | 	struct tree *trees[MAX_UNPACK_TREES]; | ||||||
|  | 	struct unpack_trees_options opts; | ||||||
|  | 	struct tree_desc t[MAX_UNPACK_TREES]; | ||||||
|  | 	int i, fd, nr_trees = 0; | ||||||
|  | 	struct dir_struct dir; | ||||||
|  | 	struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file)); | ||||||
|  |  | ||||||
|  | 	refresh_cache(REFRESH_QUIET); | ||||||
|  |  | ||||||
|  | 	fd = hold_locked_index(lock_file, 1); | ||||||
|  |  | ||||||
|  | 	memset(&trees, 0, sizeof(trees)); | ||||||
|  | 	memset(&opts, 0, sizeof(opts)); | ||||||
|  | 	memset(&t, 0, sizeof(t)); | ||||||
|  | 	if (overwrite_ignore) { | ||||||
|  | 		memset(&dir, 0, sizeof(dir)); | ||||||
|  | 		dir.flags |= DIR_SHOW_IGNORED; | ||||||
|  | 		setup_standard_excludes(&dir); | ||||||
|  | 		opts.dir = &dir; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	opts.head_idx = 1; | ||||||
|  | 	opts.src_index = &the_index; | ||||||
|  | 	opts.dst_index = &the_index; | ||||||
|  | 	opts.update = 1; | ||||||
|  | 	opts.verbose_update = 1; | ||||||
|  | 	opts.merge = 1; | ||||||
|  | 	opts.fn = twoway_merge; | ||||||
|  | 	setup_unpack_trees_porcelain(&opts, "merge"); | ||||||
|  |  | ||||||
|  | 	trees[nr_trees] = parse_tree_indirect(head); | ||||||
|  | 	if (!trees[nr_trees++]) | ||||||
|  | 		return -1; | ||||||
|  | 	trees[nr_trees] = parse_tree_indirect(remote); | ||||||
|  | 	if (!trees[nr_trees++]) | ||||||
|  | 		return -1; | ||||||
|  | 	for (i = 0; i < nr_trees; i++) { | ||||||
|  | 		parse_tree(trees[i]); | ||||||
|  | 		init_tree_desc(t+i, trees[i]->buffer, trees[i]->size); | ||||||
|  | 	} | ||||||
|  | 	if (unpack_trees(nr_trees, t, &opts)) | ||||||
|  | 		return -1; | ||||||
|  | 	if (write_cache(fd, active_cache, active_nr) || | ||||||
|  | 		commit_locked_index(lock_file)) | ||||||
|  | 		die(_("unable to write new index file")); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | @ -191,7 +191,7 @@ static int fast_forward_to(const unsigned char *to, const unsigned char *from) | ||||||
| 	struct ref_lock *ref_lock; | 	struct ref_lock *ref_lock; | ||||||
|  |  | ||||||
| 	read_cache(); | 	read_cache(); | ||||||
| 	if (checkout_fast_forward(from, to)) | 	if (checkout_fast_forward(from, to, 1)) | ||||||
| 		exit(1); /* the callee should have complained already */ | 		exit(1); /* the callee should have complained already */ | ||||||
| 	ref_lock = lock_any_ref_for_update("HEAD", from, 0); | 	ref_lock = lock_any_ref_for_update("HEAD", from, 0); | ||||||
| 	return write_ref_sha1(ref_lock, to, "cherry-pick"); | 	return write_ref_sha1(ref_lock, to, "cherry-pick"); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Nguyễn Thái Ngọc Duy
						Nguyễn Thái Ngọc Duy