예제 #1
0
파일: rm.c 프로젝트: 00027jang27/git
static int check_submodules_use_gitfiles(void)
{
	int i;
	int errs = 0;

	for (i = 0; i < list.nr; i++) {
		const char *name = list.entry[i].name;
		int pos;
		struct cache_entry *ce;
		struct stat st;

		pos = cache_name_pos(name, strlen(name));
		if (pos < 0) {
			pos = get_ours_cache_pos(name, pos);
			if (pos < 0)
				continue;
		}
		ce = active_cache[pos];

		if (!S_ISGITLINK(ce->ce_mode) ||
		    (lstat(ce->name, &st) < 0) ||
		    is_empty_dir(name))
			continue;

		if (!submodule_uses_gitfile(name))
			errs = error(_("submodule '%s' (or one of its nested "
				     "submodules) uses a .git directory\n"
				     "(use 'rm -rf' if you really want to remove "
				     "it including all of its history)"), name);
	}

	return errs;
}
예제 #2
0
파일: rm.c 프로젝트: 136357477/git
static int check_submodules_use_gitfiles(void)
{
	int i;
	int errs = 0;
	struct string_list files = STRING_LIST_INIT_NODUP;

	for (i = 0; i < list.nr; i++) {
		const char *name = list.entry[i].name;
		int pos;
		const struct cache_entry *ce;

		pos = cache_name_pos(name, strlen(name));
		if (pos < 0) {
			pos = get_ours_cache_pos(name, pos);
			if (pos < 0)
				continue;
		}
		ce = active_cache[pos];

		if (!S_ISGITLINK(ce->ce_mode) ||
		    !file_exists(ce->name) ||
		    is_empty_dir(name))
			continue;

		if (!submodule_uses_gitfile(name))
			string_list_append(&files, name);
	}

	error_removing_concrete_submodules(&files, &errs);

	return errs;
}
예제 #3
0
파일: rm.c 프로젝트: SuguruTakahashi/git
static void submodules_absorb_gitdir_if_needed(const char *prefix)
{
	int i;
	for (i = 0; i < list.nr; i++) {
		const char *name = list.entry[i].name;
		int pos;
		const struct cache_entry *ce;

		pos = cache_name_pos(name, strlen(name));
		if (pos < 0) {
			pos = get_ours_cache_pos(name, pos);
			if (pos < 0)
				continue;
		}
		ce = active_cache[pos];

		if (!S_ISGITLINK(ce->ce_mode) ||
		    !file_exists(ce->name) ||
		    is_empty_dir(name))
			continue;

		if (!submodule_uses_gitfile(name))
			absorb_git_dir_into_superproject(prefix, name,
				ABSORB_GITDIR_RECURSE_SUBMODULES);
	}
}
예제 #4
0
파일: submodule.c 프로젝트: 7sOddities/git
int ok_to_remove_submodule(const char *path)
{
	struct stat st;
	ssize_t len;
	struct child_process cp;
	const char *argv[] = {
		"status",
		"--porcelain",
		"-u",
		"--ignore-submodules=none",
		NULL,
	};
	struct strbuf buf = STRBUF_INIT;
	int ok_to_remove = 1;

	if ((lstat(path, &st) < 0) || is_empty_dir(path))
		return 1;

	if (!submodule_uses_gitfile(path))
		return 0;

	memset(&cp, 0, sizeof(cp));
	cp.argv = argv;
	cp.env = local_repo_env;
	cp.git_cmd = 1;
	cp.no_stdin = 1;
	cp.out = -1;
	cp.dir = path;
	if (start_command(&cp))
		die("Could not run 'git status --porcelain -uall --ignore-submodules=none' in submodule %s", path);

	len = strbuf_read(&buf, cp.out, 1024);
	if (len > 2)
		ok_to_remove = 0;
	close(cp.out);

	if (finish_command(&cp))
		die("'git status --porcelain -uall --ignore-submodules=none' failed in submodule %s", path);

	strbuf_release(&buf);
	return ok_to_remove;
}
예제 #5
0
파일: submodule.c 프로젝트: 136357477/git
int ok_to_remove_submodule(const char *path)
{
	ssize_t len;
	struct child_process cp = CHILD_PROCESS_INIT;
	const char *argv[] = {
		"status",
		"--porcelain",
		"-u",
		"--ignore-submodules=none",
		NULL,
	};
	struct strbuf buf = STRBUF_INIT;
	int ok_to_remove = 1;

	if (!file_exists(path) || is_empty_dir(path))
		return 1;

	if (!submodule_uses_gitfile(path))
		return 0;

	cp.argv = argv;
	prepare_submodule_repo_env(&cp.env_array);
	cp.git_cmd = 1;
	cp.no_stdin = 1;
	cp.out = -1;
	cp.dir = path;
	if (start_command(&cp))
		die("Could not run 'git status --porcelain -uall --ignore-submodules=none' in submodule %s", path);

	len = strbuf_read(&buf, cp.out, 1024);
	if (len > 2)
		ok_to_remove = 0;
	close(cp.out);

	if (finish_command(&cp))
		die("'git status --porcelain -uall --ignore-submodules=none' failed in submodule %s", path);

	strbuf_release(&buf);
	return ok_to_remove;
}
예제 #6
0
int depopulate_submodule(const char *path)
{
	struct strbuf dot_git = STRBUF_INIT;
	struct child_process cp;
	const char *argv[] = {"rm", "-rf", path, NULL};

	/* Is it populated? */
	strbuf_addf(&dot_git, "%s/.git", path);
	if (!resolve_gitdir(dot_git.buf)) {
		strbuf_release(&dot_git);
		return 0;
	}
	strbuf_release(&dot_git);

	/* Does it have a .git directory? */
	if (!submodule_uses_gitfile(path)) {
		warning(_("cannot remove submodule '%s' because it (or one of "
			  "its nested submodules) uses a .git directory"),
			  path);
		return -1;
	}

	/* Remove the whole submodule directory */
	memset(&cp, 0, sizeof(cp));
	cp.argv = argv;
	cp.env = local_repo_env;
	cp.git_cmd = 0;
	cp.no_stdin = 1;
	if (run_command(&cp)) {
		warning("Could not remove submodule %s", path);
		strbuf_release(&dot_git);
		return -1;
	}

	return 0;
}
예제 #7
0
파일: rm.c 프로젝트: 00027jang27/git
static int check_local_mod(unsigned char *head, int index_only)
{
	/*
	 * Items in list are already sorted in the cache order,
	 * so we could do this a lot more efficiently by using
	 * tree_desc based traversal if we wanted to, but I am
	 * lazy, and who cares if removal of files is a tad
	 * slower than the theoretical maximum speed?
	 */
	int i, no_head;
	int errs = 0;

	no_head = is_null_sha1(head);
	for (i = 0; i < list.nr; i++) {
		struct stat st;
		int pos;
		struct cache_entry *ce;
		const char *name = list.entry[i].name;
		unsigned char sha1[20];
		unsigned mode;
		int local_changes = 0;
		int staged_changes = 0;

		pos = cache_name_pos(name, strlen(name));
		if (pos < 0) {
			/*
			 * Skip unmerged entries except for populated submodules
			 * that could lose history when removed.
			 */
			pos = get_ours_cache_pos(name, pos);
			if (pos < 0)
				continue;

			if (!S_ISGITLINK(active_cache[pos]->ce_mode) ||
			    is_empty_dir(name))
				continue;
		}
		ce = active_cache[pos];

		if (lstat(ce->name, &st) < 0) {
			if (errno != ENOENT && errno != ENOTDIR)
				warning("'%s': %s", ce->name, strerror(errno));
			/* It already vanished from the working tree */
			continue;
		}
		else if (S_ISDIR(st.st_mode)) {
			/* if a file was removed and it is now a
			 * directory, that is the same as ENOENT as
			 * far as git is concerned; we do not track
			 * directories unless they are submodules.
			 */
			if (!S_ISGITLINK(ce->ce_mode))
				continue;
		}

		/*
		 * "rm" of a path that has changes need to be treated
		 * carefully not to allow losing local changes
		 * accidentally.  A local change could be (1) file in
		 * work tree is different since the index; and/or (2)
		 * the user staged a content that is different from
		 * the current commit in the index.
		 *
		 * In such a case, you would need to --force the
		 * removal.  However, "rm --cached" (remove only from
		 * the index) is safe if the index matches the file in
		 * the work tree or the HEAD commit, as it means that
		 * the content being removed is available elsewhere.
		 */

		/*
		 * Is the index different from the file in the work tree?
		 * If it's a submodule, is its work tree modified?
		 */
		if (ce_match_stat(ce, &st, 0) ||
		    (S_ISGITLINK(ce->ce_mode) &&
		     !ok_to_remove_submodule(ce->name)))
			local_changes = 1;

		/*
		 * Is the index different from the HEAD commit?  By
		 * definition, before the very initial commit,
		 * anything staged in the index is treated by the same
		 * way as changed from the HEAD.
		 */
		if (no_head
		     || get_tree_entry(head, name, sha1, &mode)
		     || ce->ce_mode != create_ce_mode(mode)
		     || hashcmp(ce->sha1, sha1))
			staged_changes = 1;

		/*
		 * If the index does not match the file in the work
		 * tree and if it does not match the HEAD commit
		 * either, (1) "git rm" without --cached definitely
		 * will lose information; (2) "git rm --cached" will
		 * lose information unless it is about removing an
		 * "intent to add" entry.
		 */
		if (local_changes && staged_changes) {
			if (!index_only || !(ce->ce_flags & CE_INTENT_TO_ADD))
				errs = error(_("'%s' has staged content different "
					     "from both the file and the HEAD\n"
					     "(use -f to force removal)"), name);
		}
		else if (!index_only) {
			if (staged_changes)
				errs = error(_("'%s' has changes staged in the index\n"
					     "(use --cached to keep the file, "
					     "or -f to force removal)"), name);
			if (local_changes) {
				if (S_ISGITLINK(ce->ce_mode) &&
				    !submodule_uses_gitfile(name)) {
					errs = error(_("submodule '%s' (or one of its nested "
						     "submodules) uses a .git directory\n"
						     "(use 'rm -rf' if you really want to remove "
						     "it including all of its history)"), name);
				} else
					errs = error(_("'%s' has local modifications\n"
						     "(use --cached to keep the file, "
						     "or -f to force removal)"), name);
			}
		}
	}
	return errs;
}