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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).