Exemplo n.º 1
0
static void wt_status_collect_changes_initial(struct wt_status *s)
{
	struct pathspec pathspec;
	int i;

	init_pathspec(&pathspec, s->pathspec);
	for (i = 0; i < active_nr; i++) {
		struct string_list_item *it;
		struct wt_status_change_data *d;
		struct cache_entry *ce = active_cache[i];

		if (!ce_path_match(ce, &pathspec))
			continue;
		it = string_list_insert(&s->change, ce->name);
		d = it->util;
		if (!d) {
			d = xcalloc(1, sizeof(*d));
			it->util = d;
		}
		if (ce_stage(ce)) {
			d->index_status = DIFF_STATUS_UNMERGED;
			d->stagemask |= (1 << (ce_stage(ce) - 1));
		}
		else
			d->index_status = DIFF_STATUS_ADDED;
	}
	free_pathspec(&pathspec);
}
Exemplo n.º 2
0
Arquivo: archive.c Projeto: B-Rich/git
static int path_exists(struct tree *tree, const char *path)
{
	const char *paths[] = { path, NULL };
	struct pathspec pathspec;
	int ret;

	parse_pathspec(&pathspec, 0, 0, "", paths);
	ret = read_tree_recursive(tree, "", 0, 0, &pathspec, reject_entry, NULL);
	free_pathspec(&pathspec);
	return ret != 0;
}
Exemplo n.º 3
0
static int do_reupdate(int ac, const char **av,
		       const char *prefix, int prefix_length)
{
	/* Read HEAD and run update-index on paths that are
	 * merged and already different between index and HEAD.
	 */
	int pos;
	int has_head = 1;
	struct pathspec pathspec;

	parse_pathspec(&pathspec, 0,
		       PATHSPEC_PREFER_CWD,
		       prefix, av + 1);

	if (read_ref("HEAD", head_sha1))
		/* If there is no HEAD, that means it is an initial
		 * commit.  Update everything in the index.
		 */
		has_head = 0;
 redo:
	for (pos = 0; pos < active_nr; pos++) {
		const struct cache_entry *ce = active_cache[pos];
		struct cache_entry *old = NULL;
		int save_nr;
		char *path;

		if (ce_stage(ce) || !ce_path_match(ce, &pathspec, NULL))
			continue;
		if (has_head)
			old = read_one_ent(NULL, head_sha1,
					   ce->name, ce_namelen(ce), 0);
		if (old && ce->ce_mode == old->ce_mode &&
		    !hashcmp(ce->sha1, old->sha1)) {
			free(old);
			continue; /* unchanged */
		}
		/* Be careful.  The working tree may not have the
		 * path anymore, in which case, under 'allow_remove',
		 * or worse yet 'allow_replace', active_nr may decrease.
		 */
		save_nr = active_nr;
		path = xstrdup(ce->name);
		update_one(path);
		free(path);
		if (save_nr != active_nr)
			goto redo;
	}
	free_pathspec(&pathspec);
	return 0;
}
Exemplo n.º 4
0
int write_archive_entries(struct archiver_args *args,
		write_archive_entry_fn_t write_entry)
{
	struct archiver_context context;
	struct unpack_trees_options opts;
	struct tree_desc t;
	struct pathspec pathspec;
	int err;

	if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
		size_t len = args->baselen;

		while (len > 1 && args->base[len - 2] == '/')
			len--;
		if (args->verbose)
			fprintf(stderr, "%.*s\n", (int)len, args->base);
		err = write_entry(args, args->tree->object.sha1, args->base,
				  len, 040777);
		if (err)
			return err;
	}

	context.args = args;
	context.write_entry = write_entry;

	/*
	 * Setup index and instruct attr to read index only
	 */
	if (!args->worktree_attributes) {
		memset(&opts, 0, sizeof(opts));
		opts.index_only = 1;
		opts.head_idx = -1;
		opts.src_index = &the_index;
		opts.dst_index = &the_index;
		opts.fn = oneway_merge;
		init_tree_desc(&t, args->tree->buffer, args->tree->size);
		if (unpack_trees(1, &t, &opts))
			return -1;
		git_attr_set_direction(GIT_ATTR_INDEX, &the_index);
	}

	init_pathspec(&pathspec, args->pathspec);
	err = read_tree_recursive(args->tree, "", 0, 0, &pathspec,
				  write_archive_entry, &context);
	free_pathspec(&pathspec);
	if (err == READ_TREE_RECURSIVE)
		err = 0;
	return err;
}
Exemplo n.º 5
0
int git_checkout_file(const char *ref, const char *path, const char *outputpath)
{
	struct cache_entry *ce;
	int ret;
	GIT_HASH sha1;
	struct tree * root;
	struct checkout state;
	struct pathspec pathspec;
	const char *match[2];
	ret = get_sha1(ref, sha1);
	if(ret)
		return ret;

	reprepare_packed_git();
	root = parse_tree_indirect(sha1);

	if(!root)
	{
		free_all_pack();
		return -1;
	}

	ce = xcalloc(1, cache_entry_size(strlen(path)));

	match[0] = path;
	match[1] = NULL;

	init_pathspec(&pathspec, match);
	pathspec.items[0].use_wildcard = 0;
	ret = read_tree_recursive(root, "", 0, 0, &pathspec, update_some, ce);
	free_pathspec(&pathspec);

	if(ret)
	{
		free_all_pack();
		free(ce);
		return ret;
	}
	memset(&state, 0, sizeof(state));
	state.force = 1;
	state.refresh_cache = 0;

	ret = write_entry(ce, outputpath, &state, 0);
	free_all_pack();
	free(ce);
	return ret;
}
Exemplo n.º 6
0
static int read_from_tree(const struct pathspec *pathspec,
			  unsigned char *tree_sha1)
{
	struct diff_options opt;

	memset(&opt, 0, sizeof(opt));
	copy_pathspec(&opt.pathspec, pathspec);
	opt.output_format = DIFF_FORMAT_CALLBACK;
	opt.format_callback = update_index_from_diff;

	read_cache();
	if (do_diff_cache(tree_sha1, &opt))
		return 1;
	diffcore_std(&opt);
	diff_flush(&opt);
	free_pathspec(&opt.pathspec);

	return 0;
}
Exemplo n.º 7
0
static void *preload_thread(void *_data)
{
	int nr;
	struct thread_data *p = _data;
	struct index_state *index = p->index;
	struct cache_entry **cep = index->cache + p->offset;
	struct cache_def cache;
	struct pathspec pathspec;

	init_pathspec(&pathspec, p->pathspec);
	memset(&cache, 0, sizeof(cache));
	nr = p->nr;
	if (nr + p->offset > index->cache_nr)
		nr = index->cache_nr - p->offset;

	do {
		struct cache_entry *ce = *cep++;
		struct stat st;

		if (ce_stage(ce))
			continue;
		if (S_ISGITLINK(ce->ce_mode))
			continue;
		if (ce_uptodate(ce))
			continue;
		if (!ce_path_match(ce, &pathspec))
			continue;
		if (threaded_has_symlink_leading_path(&cache, ce->name, ce_namelen(ce)))
			continue;
		if (lstat(ce->name, &st))
			continue;
		if (ie_match_stat(index, ce, &st, CE_MATCH_RACY_IS_DIRTY))
			continue;
		ce_mark_uptodate(ce);
	} while (--nr > 0);
	free_pathspec(&pathspec);
	return NULL;
}
Exemplo n.º 8
0
Arquivo: add.c Projeto: 13leaf/git
int cmd_add(int argc, const char **argv, const char *prefix)
{
	int exit_status = 0;
	int newfd;
	struct pathspec pathspec;
	struct dir_struct dir;
	int flags;
	int add_new_files;
	int require_pathspec;
	char *seen = NULL;
	int implicit_dot = 0;
	struct update_callback_data update_data;

	git_config(add_config, NULL);

	argc = parse_options(argc, argv, prefix, builtin_add_options,
			  builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
	if (patch_interactive)
		add_interactive = 1;
	if (add_interactive)
		exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));

	if (edit_interactive)
		return(edit_patch(argc, argv, prefix));
	argc--;
	argv++;

	if (0 <= addremove_explicit)
		addremove = addremove_explicit;
	else if (take_worktree_changes && ADDREMOVE_DEFAULT)
		addremove = 0; /* "-u" was given but not "-A" */

	if (addremove && take_worktree_changes)
		die(_("-A and -u are mutually incompatible"));

	/*
	 * Warn when "git add pathspec..." was given without "-u" or "-A"
	 * and pathspec... covers a removed path.
	 */
	memset(&update_data, 0, sizeof(update_data));
	if (!take_worktree_changes && addremove_explicit < 0)
		update_data.warn_add_would_remove = 1;

	if (!take_worktree_changes && addremove_explicit < 0 && argc)
		/*
		 * Turn "git add pathspec..." to "git add -A pathspec..."
		 * in Git 2.0 but not yet
		 */
		; /* addremove = 1; */

	if (!show_only && ignore_missing)
		die(_("Option --ignore-missing can only be used together with --dry-run"));
	if (addremove) {
		option_with_implicit_dot = "--all";
		short_option_with_implicit_dot = "-A";
	}
	if (take_worktree_changes) {
		option_with_implicit_dot = "--update";
		short_option_with_implicit_dot = "-u";
	}
	if (option_with_implicit_dot && !argc) {
		static const char *here[2] = { ".", NULL };
		argc = 1;
		argv = here;
		implicit_dot = 1;
	}

	add_new_files = !take_worktree_changes && !refresh_only;
	require_pathspec = !take_worktree_changes;

	newfd = hold_locked_index(&lock_file, 1);

	flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
		 (show_only ? ADD_CACHE_PRETEND : 0) |
		 (intent_to_add ? ADD_CACHE_INTENT : 0) |
		 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
		 (!(addremove || take_worktree_changes)
		  ? ADD_CACHE_IGNORE_REMOVAL : 0)) |
		 (implicit_dot ? ADD_CACHE_IMPLICIT_DOT : 0);

	if (require_pathspec && argc == 0) {
		fprintf(stderr, _("Nothing specified, nothing added.\n"));
		fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
		return 0;
	}

	if (read_cache() < 0)
		die(_("index file corrupt"));

	/*
	 * Check the "pathspec '%s' did not match any files" block
	 * below before enabling new magic.
	 */
	parse_pathspec(&pathspec, 0,
		       PATHSPEC_PREFER_FULL |
		       PATHSPEC_SYMLINK_LEADING_PATH |
		       PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE,
		       prefix, argv);

	if (add_new_files) {
		int baselen;
		struct pathspec empty_pathspec;

		/* Set up the default git porcelain excludes */
		memset(&dir, 0, sizeof(dir));
		if (!ignored_too) {
			dir.flags |= DIR_COLLECT_IGNORED;
			setup_standard_excludes(&dir);
		}

		memset(&empty_pathspec, 0, sizeof(empty_pathspec));
		/* This picks up the paths that are not tracked */
		baselen = fill_directory(&dir, implicit_dot ? &empty_pathspec : &pathspec);
		if (pathspec.nr)
			seen = prune_directory(&dir, &pathspec, baselen,
					implicit_dot ? WARN_IMPLICIT_DOT : 0);
	}

	if (refresh_only) {
		refresh(verbose, &pathspec);
		goto finish;
	}
	if (implicit_dot && prefix)
		refresh_cache(REFRESH_QUIET);

	if (pathspec.nr) {
		int i;

		if (!seen)
			seen = find_pathspecs_matching_against_index(&pathspec);

		/*
		 * file_exists() assumes exact match
		 */
		GUARD_PATHSPEC(&pathspec,
			       PATHSPEC_FROMTOP |
			       PATHSPEC_LITERAL |
			       PATHSPEC_GLOB |
			       PATHSPEC_ICASE);

		for (i = 0; i < pathspec.nr; i++) {
			const char *path = pathspec.items[i].match;
			if (!seen[i] &&
			    ((pathspec.items[i].magic &
			      (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
			     !file_exists(path))) {
				if (ignore_missing) {
					int dtype = DT_UNKNOWN;
					if (is_excluded(&dir, path, &dtype))
						dir_add_ignored(&dir, path, pathspec.items[i].len);
				} else
					die(_("pathspec '%s' did not match any files"),
					    pathspec.items[i].original);
			}
		}
		free(seen);
	}

	plug_bulk_checkin();

	if ((flags & ADD_CACHE_IMPLICIT_DOT) && prefix) {
		/*
		 * Check for modified files throughout the worktree so
		 * update_callback has a chance to warn about changes
		 * outside the cwd.
		 */
		update_data.implicit_dot = prefix;
		update_data.implicit_dot_len = strlen(prefix);
		free_pathspec(&pathspec);
		memset(&pathspec, 0, sizeof(pathspec));
	}
	update_data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
	update_files_in_cache(prefix, &pathspec, &update_data);

	exit_status |= !!update_data.add_errors;
	if (add_new_files)
		exit_status |= add_files(&dir, flags);

	unplug_bulk_checkin();

finish:
	if (active_cache_changed) {
		if (write_cache(newfd, active_cache, active_nr) ||
		    commit_locked_index(&lock_file))
			die(_("Unable to write new index file"));
	}

	return exit_status;
}