All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gummerer <t.gummerer@gmail.com>
To: git@vger.kernel.org
Cc: t.gummerer@gmail.com, gitster@pobox.com, tr@thomasrast.ch,
	mhagger@alum.mit.edu, pclouds@gmail.com,
	robin.rosenberg@dewire.com, sunshine@sunshineco.com,
	ramsay@ramsay1.demon.co.uk
Subject: [PATCH v4 17/24] read-cache: write resolve-undo data for index-v5
Date: Wed, 27 Nov 2013 13:00:52 +0100	[thread overview]
Message-ID: <1385553659-9928-18-git-send-email-t.gummerer@gmail.com> (raw)
In-Reply-To: <1385553659-9928-1-git-send-email-t.gummerer@gmail.com>

Make git read the resolve-undo data from the index.

Since the resolve-undo data is joined with the conflicts in the ondisk
format of the index file version 5, conflicts and resolved data is read
at the same time, and the resolve-undo data is then converted to the
in-memory format.

Helped-by: Thomas Rast <trast@student.ethz.ch>
Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
---
 read-cache-v5.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 191 insertions(+), 8 deletions(-)

diff --git a/read-cache-v5.c b/read-cache-v5.c
index 0d06cfe..a5e9b5a 100644
--- a/read-cache-v5.c
+++ b/read-cache-v5.c
@@ -723,6 +723,29 @@ static void ondisk_from_directory_entry(struct directory_entry *de,
 	}
 }
 
+static struct conflict_part *conflict_part_from_inmemory(struct cache_entry *ce)
+{
+	struct conflict_part *conflict;
+	int flags;
+
+	conflict = xmalloc(sizeof(struct conflict_part));
+	flags                = CONFLICT_CONFLICTED;
+	flags               |= ce_stage(ce) << CONFLICT_STAGESHIFT;
+	conflict->flags      = flags;
+	conflict->entry_mode = ce->ce_mode;
+	conflict->next       = NULL;
+	hashcpy(conflict->sha1, ce->sha1);
+	return conflict;
+}
+
+static void conflict_to_ondisk(struct conflict_part *cp,
+			       struct ondisk_conflict_part *ondisk)
+{
+	ondisk->flags      = htons(cp->flags);
+	ondisk->entry_mode = htons(cp->entry_mode);
+	hashcpy(ondisk->sha1, cp->sha1);
+}
+
 static void insert_directory_entry(struct directory_entry *de,
 				   struct hash_table *table,
 				   unsigned int *total_dir_len,
@@ -789,6 +812,11 @@ static struct directory_entry *get_directory(char *dir, unsigned int dir_len,
 	return ret;
 }
 
+static struct conflict_entry *create_conflict_entry_from_ce(struct cache_entry *ce)
+{
+	return create_new_conflict(ce->name, ce_namelen(ce));
+}
+
 static void convert_one_to_ondisk(struct hash_table *table, struct cache_tree *it,
 				  const char *path, int pathlen, uint32_t crc)
 {
@@ -840,6 +868,52 @@ static void cache_tree_to_ondisk(struct hash_table *table, struct cache_tree *ro
 	convert_one_to_ondisk(table, root, "", 0, 0);
 }
 
+static void resolve_undo_to_ondisk(struct string_list *resolve_undo,
+				   struct conflict_entry **conflict_queue)
+{
+	struct string_list_item *item;
+	struct conflict_entry *current = *conflict_queue;
+
+	if (!resolve_undo)
+		return;
+	for_each_string_list_item(item, resolve_undo) {
+		struct conflict_entry *conflict_entry;
+		struct resolve_undo_info *ui = item->util;
+		int i, len;
+
+		if (!ui)
+			continue;
+
+		len = strlen(item->string);
+		while (current && current->next &&
+		       cache_name_compare(current->name, current->namelen,
+					  item->string, len))
+			current = current->next;
+
+		conflict_entry = create_new_conflict(item->string, len);
+		for (i = 0; i < 3; i++) {
+			if (ui->mode[i]) {
+				struct conflict_part *cp;
+
+				cp = xmalloc(sizeof(struct conflict_part));
+				cp->flags = (i + 1) << CONFLICT_STAGESHIFT;
+				cp->entry_mode = ui->mode[i];
+				cp->next = NULL;
+				hashcpy(cp->sha1, ui->sha1[i]);
+				add_part_to_conflict_entry(conflict_entry, cp);
+			}
+		}
+		if (!*conflict_queue) {
+			*conflict_queue = conflict_entry;
+			conflict_entry->next = NULL;
+			current = conflict_entry;
+		} else {
+			conflict_entry->next = current->next;
+			current->next = conflict_entry;
+		}
+	}
+}
+
 static void ce_queue_push(struct cache_entry **head,
 			  struct cache_entry **tail,
 			  struct cache_entry *ce)
@@ -855,15 +929,32 @@ static void ce_queue_push(struct cache_entry **head,
 	*tail = (*tail)->next_ce;
 }
 
+static void conflict_queue_push(struct conflict_entry **head,
+				struct conflict_entry **tail,
+				struct conflict_entry *conflict)
+{
+	if (!*head) {
+		*head = *tail = conflict;
+		(*tail)->next = NULL;
+		return;
+	}
+
+	(*tail)->next = conflict;
+	conflict->next = NULL;
+	*tail = (*tail)->next;
+}
+
 static struct directory_entry *compile_directory_data(struct index_state *istate,
 						      int nfile, unsigned int *ndir,
 						      unsigned int *total_dir_len,
-						      unsigned int *total_file_len)
+						      unsigned int *total_file_len,
+						      struct conflict_entry **conflict_queue)
 {
 	int i, dir_len = -1;
 	char *dir;
 	struct directory_entry *de, *current, *search;
 	struct cache_entry **cache = istate->cache;
+	struct conflict_entry *conflict_entry = NULL, *tail;
 	struct hash_table table;
 	uint32_t crc;
 
@@ -894,9 +985,22 @@ static struct directory_entry *compile_directory_data(struct index_state *istate
 		if (search->de_pathlen)
 			*total_file_len -= search->de_pathlen + 1;
 		ce_queue_push(&(search->ce), &(search->ce_last), cache[i]);
+
+		if (ce_stage(cache[i]) > 0) {
+			struct conflict_part *conflict_part;
+			if (!conflict_entry ||
+			    cache_name_compare(conflict_entry->name, conflict_entry->namelen,
+					       cache[i]->name, ce_namelen(cache[i]))) {
+				conflict_entry = create_conflict_entry_from_ce(cache[i]);
+				conflict_queue_push(conflict_queue, &tail, conflict_entry);
+			}
+			conflict_part = conflict_part_from_inmemory(cache[i]);
+			add_part_to_conflict_entry(conflict_entry, conflict_part);
+		}
 	}
 	if (istate->cache_tree)
 		cache_tree_to_ondisk(&table, istate->cache_tree);
+	resolve_undo_to_ondisk(istate->resolve_undo, conflict_queue);
 	return de;
 }
 
@@ -1062,16 +1166,82 @@ static int write_entries(struct index_state *istate,
 	return 0;
 }
 
+static int write_conflict(struct conflict_entry *conflict, int fd)
+{
+	struct conflict_entry *current;
+	struct conflict_part *current_part;
+	uint32_t crc;
+
+	current = conflict;
+	while (current) {
+		unsigned int to_write, i;
+
+		crc = 0;
+		if (ce_write(&crc, fd, current->name, current->namelen) < 0)
+			return -1;
+		if (ce_write(&crc, fd, "\0", 1) < 0)
+			return -1;
+		to_write = htonl(current->nfileconflicts);
+		if (ce_write(&crc, fd, (Bytef*)&to_write, 4) < 0)
+			return -1;
+		current_part = current->entries;
+		for (i = 0; i < current->nfileconflicts; i++) {
+			struct ondisk_conflict_part ondisk;
+
+			conflict_to_ondisk(current_part, &ondisk);
+			if (ce_write(&crc, fd, (Bytef*)&ondisk, sizeof(struct ondisk_conflict_part)) < 0)
+				return 0;
+			current_part = current_part->next;
+		}
+		crc = htonl(crc);
+		if (ce_write(NULL, fd, &crc, 4) < 0)
+			return -1;
+		current = current->next;
+	}
+	return 0;
+}
+
+static int write_resolve_undo(struct index_state *istate,
+			      struct conflict_entry *conflict_queue,
+			      int fd)
+{
+	struct conflict_entry *current;
+	int nr = 0;
+	uint32_t crc = 0, to_write;
+
+	/* Just count */
+	for (current = conflict_queue; current; current = current->next)
+		nr++;
+
+	if (ce_write(&crc, fd, "REUC", 4) < 0)
+		return -1;
+	to_write = htonl(nr);
+	if (ce_write(&crc, fd, &to_write, 4) < 0)
+		return -1;
+	to_write = htonl(crc);
+	if (ce_write(NULL, fd, &to_write, 4) < 0)
+		return -1;
+
+	current = conflict_queue;
+	while (current) {
+		if (write_conflict(current, fd) < 0)
+			return -1;
+		current = current->next;
+	}
+	return 0;
+}
+
 static int write_index_v5(struct index_state *istate, int newfd)
 {
 	struct cache_header hdr;
 	struct cache_header_v5 hdr_v5;
 	struct cache_entry **cache = istate->cache;
 	struct directory_entry *de;
+	struct conflict_entry *conflict_queue = NULL;
 	unsigned int entries = istate->cache_nr;
 	unsigned int i, removed, total_dir_len;
 	unsigned int total_file_len, foffsetblock;
-	unsigned int ndir;
+	unsigned int ndir, extoffset, nextension;
 	uint32_t crc;
 
 	if (istate->filter_opts)
@@ -1084,24 +1254,34 @@ static int write_index_v5(struct index_state *istate, int newfd)
 	hdr.hdr_signature = htonl(CACHE_SIGNATURE);
 	hdr.hdr_version = htonl(istate->version);
 	hdr.hdr_entries = htonl(entries - removed);
-	hdr_v5.hdr_nextension = htonl(0); /* Currently no extensions are supported */
 
 	total_dir_len = 0;
 	total_file_len = 0;
 	de = compile_directory_data(istate, entries, &ndir,
-				    &total_dir_len, &total_file_len);
+				    &total_dir_len, &total_file_len,
+				    &conflict_queue);
 	hdr_v5.hdr_ndir = htonl(ndir);
 
-	foffsetblock = sizeof(hdr) + sizeof(hdr_v5) + 4
-		+ (ndir + 1) * 4
-		+ total_dir_len
-		+ ndir * (offsetof(struct ondisk_directory_entry, name) + 4);
+	nextension = (istate->resolve_undo || conflict_queue) ? 1 : 0;
+	foffsetblock = sizeof(hdr) + sizeof(hdr_v5) + (nextension * 4) + 4 +
+		(ndir + 1) * 4 + total_dir_len +
+		ndir * (offsetof(struct ondisk_directory_entry, name) + 4);
 	hdr_v5.hdr_fblockoffset = htonl(foffsetblock + (entries - removed + 1) * 4);
+	hdr_v5.hdr_nextension = htonl(nextension);
+
 	crc = 0;
 	if (ce_write(&crc, newfd, &hdr, sizeof(hdr)) < 0)
 		return -1;
 	if (ce_write(&crc, newfd, &hdr_v5, sizeof(hdr_v5)) < 0)
 		return -1;
+
+	if (nextension) {
+		extoffset = foffsetblock + (entries - removed + 1) * 4 + total_file_len +
+			(entries - removed) * (offsetof(struct ondisk_cache_entry, name) + 4);
+		extoffset = htonl(extoffset);
+		if (ce_write(&crc, newfd, &extoffset, 4) < 0)
+			return -1;
+	}
 	crc = htonl(crc);
 	if (ce_write(NULL, newfd, &crc, 4) < 0)
 		return -1;
@@ -1110,6 +1290,9 @@ static int write_index_v5(struct index_state *istate, int newfd)
 		return -1;
 	if (write_entries(istate, de, entries, newfd) < 0)
 		return -1;
+	if (nextension)
+		if (write_resolve_undo(istate, conflict_queue, newfd) < 0)
+			return -1;
 	return ce_flush(newfd);
 }
 
-- 
1.8.4.2

  parent reply	other threads:[~2013-11-27 12:02 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-11-27 12:00 [PATCH v4 00/24] Index-v5 Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 01/24] t2104: Don't fail for index versions other than [23] Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 02/24] read-cache: split index file version specific functionality Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 03/24] read-cache: move index v2 specific functions to their own file Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 04/24] read-cache: Re-read index if index file changed Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 05/24] add documentation for the index api Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 06/24] read-cache: add index reading api Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 07/24] make sure partially read index is not changed Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 08/24] grep.c: use index api Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 09/24] ls-files.c: " Thomas Gummerer
2013-11-30  9:17   ` Duy Nguyen
2013-11-30 10:30     ` Thomas Gummerer
2013-11-30 15:39   ` Antoine Pelisse
2013-11-30 20:08     ` Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 10/24] documentation: add documentation of the index-v5 file format Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 11/24] read-cache: make in-memory format aware of stat_crc Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 12/24] read-cache: read index-v5 Thomas Gummerer
2013-11-30  9:17   ` Duy Nguyen
2013-11-30 10:40     ` Thomas Gummerer
2013-11-30 12:19   ` Antoine Pelisse
2013-11-30 20:10     ` Thomas Gummerer
2013-11-30 15:26   ` Antoine Pelisse
2013-11-30 20:27     ` Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 13/24] read-cache: read resolve-undo data Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 14/24] read-cache: read cache-tree in index-v5 Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 15/24] read-cache: write index-v5 Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 16/24] read-cache: write index-v5 cache-tree data Thomas Gummerer
2013-11-27 12:00 ` Thomas Gummerer [this message]
2013-11-27 12:00 ` [PATCH v4 18/24] update-index.c: rewrite index when index-version is given Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 19/24] p0003-index.sh: add perf test for the index formats Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 20/24] introduce GIT_INDEX_VERSION environment variable Thomas Gummerer
2013-11-27 21:57   ` Eric Sunshine
2013-11-27 22:08     ` Junio C Hamano
2013-11-28  9:57       ` Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 21/24] test-lib: allow setting the index format version Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 22/24] t1600: add index v5 specific tests Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 23/24] POC for partial writing Thomas Gummerer
2013-11-30  9:58   ` Duy Nguyen
2013-11-30 10:50     ` Thomas Gummerer
2013-11-27 12:00 ` [PATCH v4 24/24] perf: add partial writing test Thomas Gummerer
2013-12-09 10:14 ` [PATCH v4 00/24] Index-v5 Thomas Gummerer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1385553659-9928-18-git-send-email-t.gummerer@gmail.com \
    --to=t.gummerer@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=mhagger@alum.mit.edu \
    --cc=pclouds@gmail.com \
    --cc=ramsay@ramsay1.demon.co.uk \
    --cc=robin.rosenberg@dewire.com \
    --cc=sunshine@sunshineco.com \
    --cc=tr@thomasrast.ch \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.