Exemple #1
0
/*
 * Read contents a file with conflicts, normalize the conflicts
 * by (1) discarding the common ancestor version in diff3-style,
 * (2) reordering our side and their side so that whichever sorts
 * alphabetically earlier comes before the other one, while
 * computing the "conflict ID", which is just an SHA-1 hash of
 * one side of the conflict, NUL, the other side of the conflict,
 * and NUL concatenated together.
 *
 * Return 1 if conflict hunks are found, 0 if there are no conflict
 * hunks and -1 if an error occured.
 */
static int handle_path(unsigned char *sha1, struct rerere_io *io, int marker_size)
{
	git_SHA_CTX ctx;
	struct strbuf buf = STRBUF_INIT, out = STRBUF_INIT;
	int has_conflicts = 0;
	if (sha1)
		git_SHA1_Init(&ctx);

	while (!io->getline(&buf, io)) {
		if (is_cmarker(buf.buf, '<', marker_size)) {
			has_conflicts = handle_conflict(&out, io, marker_size,
							sha1 ? &ctx : NULL);
			if (has_conflicts < 0)
				break;
			rerere_io_putmem(out.buf, out.len, io);
			strbuf_reset(&out);
		} else
			rerere_io_putstr(buf.buf, io);
	}
	strbuf_release(&buf);
	strbuf_release(&out);

	if (sha1)
		git_SHA1_Final(sha1, &ctx);

	return has_conflicts;
}
Exemple #2
0
/*
 * Read contents a file with conflicts, normalize the conflicts
 * by (1) discarding the common ancestor version in diff3-style,
 * (2) reordering our side and their side so that whichever sorts
 * alphabetically earlier comes before the other one, while
 * computing the "conflict ID", which is just an SHA-1 hash of
 * one side of the conflict, NUL, the other side of the conflict,
 * and NUL concatenated together.
 *
 * Return 1 if conflict hunks are found, 0 if there are no conflict
 * hunks and -1 if an error occured.
 */
static int handle_path(unsigned char *hash, struct rerere_io *io, int marker_size)
{
	git_hash_ctx ctx;
	struct strbuf buf = STRBUF_INIT, out = STRBUF_INIT;
	int has_conflicts = 0;
	if (hash)
		the_hash_algo->init_fn(&ctx);

	while (!io->getline(&buf, io)) {
		if (is_cmarker(buf.buf, '<', marker_size)) {
			has_conflicts = handle_conflict(&out, io, marker_size,
							hash ? &ctx : NULL);
			if (has_conflicts < 0)
				break;
			rerere_io_putmem(out.buf, out.len, io);
			strbuf_reset(&out);
		} else
			rerere_io_putstr(buf.buf, io);
	}
	strbuf_release(&buf);
	strbuf_release(&out);

	if (hash)
		the_hash_algo->final_fn(hash, &ctx);

	return has_conflicts;
}
Exemple #3
0
static int handle_conflict(struct strbuf *out, struct rerere_io *io,
			   int marker_size, git_hash_ctx *ctx)
{
	enum {
		RR_SIDE_1 = 0, RR_SIDE_2, RR_ORIGINAL
	} hunk = RR_SIDE_1;
	struct strbuf one = STRBUF_INIT, two = STRBUF_INIT;
	struct strbuf buf = STRBUF_INIT, conflict = STRBUF_INIT;
	int has_conflicts = -1;

	while (!io->getline(&buf, io)) {
		if (is_cmarker(buf.buf, '<', marker_size)) {
			if (handle_conflict(&conflict, io, marker_size, NULL) < 0)
				break;
			if (hunk == RR_SIDE_1)
				strbuf_addbuf(&one, &conflict);
			else
				strbuf_addbuf(&two, &conflict);
			strbuf_release(&conflict);
		} else if (is_cmarker(buf.buf, '|', marker_size)) {
			if (hunk != RR_SIDE_1)
				break;
			hunk = RR_ORIGINAL;
		} else if (is_cmarker(buf.buf, '=', marker_size)) {
			if (hunk != RR_SIDE_1 && hunk != RR_ORIGINAL)
				break;
			hunk = RR_SIDE_2;
		} else if (is_cmarker(buf.buf, '>', marker_size)) {
			if (hunk != RR_SIDE_2)
				break;
			if (strbuf_cmp(&one, &two) > 0)
				strbuf_swap(&one, &two);
			has_conflicts = 1;
			rerere_strbuf_putconflict(out, '<', marker_size);
			strbuf_addbuf(out, &one);
			rerere_strbuf_putconflict(out, '=', marker_size);
			strbuf_addbuf(out, &two);
			rerere_strbuf_putconflict(out, '>', marker_size);
			if (ctx) {
				the_hash_algo->update_fn(ctx, one.buf ?
							 one.buf : "",
							 one.len + 1);
				the_hash_algo->update_fn(ctx, two.buf ?
							 two.buf : "",
							 two.len + 1);
			}
			break;
		} else if (hunk == RR_SIDE_1)
			strbuf_addbuf(&one, &buf);
		else if (hunk == RR_ORIGINAL)
			; /* discard */
		else if (hunk == RR_SIDE_2)
			strbuf_addbuf(&two, &buf);
	}
	strbuf_release(&one);
	strbuf_release(&two);
	strbuf_release(&buf);

	return has_conflicts;
}
Exemple #4
0
static int
do_attach_branch(struct wim_dentry *branch, const utf16lechar *target,
		 struct update_command_journal *j,
		 int add_flags, wimlib_progress_func_t progfunc, void *progctx)
{
	struct wim_dentry *parent;
	struct wim_dentry *existing;
	const utf16lechar empty_name[1] = {0};
	const utf16lechar *cur_component_name;
	size_t cur_component_nbytes;
	const utf16lechar *next_component_name;
	int ret;

	/* Attempt to create root directory before proceeding to the "real"
	 * first component  */
	parent = NULL;
	existing = *j->root_p;
	cur_component_name = empty_name;
	cur_component_nbytes = 0;

	/* Skip leading slashes  */
	next_component_name = target;
	while (*next_component_name == cpu_to_le16(WIM_PATH_SEPARATOR))
		next_component_name++;

	while (*next_component_name) { /* While not the last component ... */
		const utf16lechar *end;

		if (existing) {
			/* Descend into existing directory  */
			if (!dentry_is_directory(existing)) {
				ERROR("\"%"TS"\" in the WIM image "
				      "is not a directory!",
				      dentry_full_path(existing));
				return WIMLIB_ERR_NOTDIR;
			}
		} else {
			/* A parent directory of the target didn't exist.  Make
			 * the way by creating a filler directory.  */
			struct wim_dentry *filler;

			ret = new_filler_directory(&filler);
			if (ret)
				return ret;
			ret = dentry_set_name_utf16le(filler,
						      cur_component_name,
						      cur_component_nbytes);
			if (ret) {
				free_dentry(filler);
				return ret;
			}
			ret = journaled_link(j, filler, parent);
			if (ret) {
				free_dentry(filler);
				return ret;
			}
			existing = filler;
		}

		/* Advance to next component  */

		cur_component_name = next_component_name;
		end = cur_component_name + 1;
		while (*end && *end != cpu_to_le16(WIM_PATH_SEPARATOR))
			end++;

		next_component_name = end;
		if (*end) {
			/* There will still be more components after this.  */
			do {
			} while (*++next_component_name == cpu_to_le16(WIM_PATH_SEPARATOR));
			wimlib_assert(*next_component_name);  /* No trailing slashes  */
		} else {
			/* This will be the last component  */
			next_component_name = end;
		}
		parent = existing;
		cur_component_nbytes = (end - cur_component_name) * sizeof(utf16lechar);
		existing = get_dentry_child_with_utf16le_name(
					parent,
					cur_component_name,
					cur_component_nbytes,
					WIMLIB_CASE_PLATFORM_DEFAULT);
	}

	/* Last component  */
	if (existing) {
		return handle_conflict(branch, existing, j, add_flags,
				       progfunc, progctx);
	} else {
		return journaled_link(j, branch, parent);
	}
}
Exemple #5
0
static int
handle_conflict(struct wim_dentry *branch, struct wim_dentry *existing,
		struct update_command_journal *j,
		int add_flags,
		wimlib_progress_func_t progfunc, void *progctx)
{
	bool branch_is_dir = dentry_is_directory(branch);
	bool existing_is_dir = dentry_is_directory(existing);

	if (branch_is_dir != existing_is_dir) {
		if (existing_is_dir)  {
			ERROR("\"%"TS"\" is a directory!\n"
			      "        Specify the path at which "
			      "to place the file inside this directory.",
			      dentry_full_path(existing));
			return WIMLIB_ERR_IS_DIRECTORY;
		} else {
			ERROR("Can't place directory at \"%"TS"\" because "
			      "a nondirectory file already exists there!",
			      dentry_full_path(existing));
			return WIMLIB_ERR_NOTDIR;
		}
	}

	if (branch_is_dir) {
		/* Directory overlay  */
		while (dentry_has_children(branch)) {
			struct wim_dentry *new_child;
			struct wim_dentry *existing_child;
			int ret;

			new_child = dentry_any_child(branch);

			existing_child =
				get_dentry_child_with_utf16le_name(existing,
								   new_child->file_name,
								   new_child->file_name_nbytes,
								   WIMLIB_CASE_PLATFORM_DEFAULT);
			unlink_dentry(new_child);
			if (existing_child) {
				ret = handle_conflict(new_child, existing_child,
						      j, add_flags,
						      progfunc, progctx);
			} else {
				ret = journaled_link(j, new_child, existing);
			}
			if (ret) {
				dentry_add_child(branch, new_child);
				return ret;
			}
		}
		free_dentry_tree(branch, j->lookup_table);
		return 0;
	} else if (add_flags & WIMLIB_ADD_FLAG_NO_REPLACE) {
		/* Can't replace nondirectory file  */
		ERROR("Refusing to overwrite nondirectory file \"%"TS"\"",
		      dentry_full_path(existing));
		return WIMLIB_ERR_INVALID_OVERLAY;
	} else {
		/* Replace nondirectory file  */
		struct wim_dentry *parent;
		int ret;

		parent = existing->d_parent;

		ret = calculate_dentry_full_path(existing);
		if (ret)
			return ret;

		if (add_flags & WIMLIB_ADD_FLAG_VERBOSE) {
			union wimlib_progress_info info;

			info.replace.path_in_wim = existing->_full_path;
			ret = call_progress(progfunc,
					    WIMLIB_PROGRESS_MSG_REPLACE_FILE_IN_WIM,
					    &info, progctx);
			if (ret)
				return ret;
		}

		ret = journaled_unlink(j, existing);
		if (ret)
			return ret;

		return journaled_link(j, branch, parent);
	}
}