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 += mailmap.o
 | 
			
		||||
LIB_OBJS += match-trees.o
 | 
			
		||||
LIB_OBJS += merge.o
 | 
			
		||||
LIB_OBJS += merge-file.o
 | 
			
		||||
LIB_OBJS += merge-recursive.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"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
			      struct commit_list *remoteheads,
 | 
			
		||||
			      struct commit *head, const char *head_arg)
 | 
			
		||||
| 
						 | 
				
			
			@ -762,56 +709,6 @@ static int count_unmerged_entries(void)
 | 
			
		|||
	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,
 | 
			
		||||
				   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,
 | 
			
		||||
					  commit->object.sha1)) {
 | 
			
		||||
					  commit->object.sha1,
 | 
			
		||||
					  overwrite_ignore)) {
 | 
			
		||||
			ret = 1;
 | 
			
		||||
			goto done;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										11
									
								
								cache.h
								
								
								
								
							
							
						
						
									
										11
									
								
								cache.h
								
								
								
								
							| 
						 | 
				
			
			@ -1265,8 +1265,15 @@ struct startup_info {
 | 
			
		|||
};
 | 
			
		||||
extern struct startup_info *startup_info;
 | 
			
		||||
 | 
			
		||||
/* builtin/merge.c */
 | 
			
		||||
int checkout_fast_forward(const unsigned char *from, const unsigned char *to);
 | 
			
		||||
/* merge.c */
 | 
			
		||||
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[]);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
/* 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
 | 
			
		||||
	read_cache();
 | 
			
		||||
	if (checkout_fast_forward(from, to))
 | 
			
		||||
	if (checkout_fast_forward(from, to, 1))
 | 
			
		||||
		exit(1); /* the callee should have complained already */
 | 
			
		||||
	ref_lock = lock_any_ref_for_update("HEAD", from, 0);
 | 
			
		||||
	return write_ref_sha1(ref_lock, to, "cherry-pick");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue