Skip to content

Commit 1869bbe

Browse files
committed
rerere: split conflict ID further
The plan is to keep assigning the backward compatible conflict ID based on the hash of the (normalized) text of conflicts, keep using that conflict ID as the directory name under $GIT_DIR/rr-cache/, but allow each conflicted path to use a separate "variant" to record resolutions, i.e. having more than one <preimage,postimage> pairs under $GIT_DIR/rr-cache/$ID/ directory. As the first step in that direction, separate the shared "conflict ID" out of the rerere_id structure. The plan is to keep information per $ID in rerere_dir, that can be shared among rerere_id that is per conflicted path. When we are done with rerere(), which can be directly called from other programs like "git apply", "git commit" and "git merge", the shared rerere_dir structures can be freed entirely, so they are not reference-counted and they are not freed when we release rerere_id's that reference them. Signed-off-by: Junio C Hamano <[email protected]>
1 parent f58316d commit 1869bbe

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

rerere.c

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "ll-merge.h"
99
#include "attr.h"
1010
#include "pathspec.h"
11+
#include "sha1-lookup.h"
1112

1213
#define RESOLVED 0
1314
#define PUNTED 1
@@ -22,14 +23,31 @@ static int rerere_autoupdate;
2223

2324
static char *merge_rr_path;
2425

26+
static int rerere_dir_nr;
27+
static int rerere_dir_alloc;
28+
29+
static struct rerere_dir {
30+
unsigned char sha1[20];
31+
} **rerere_dir;
32+
33+
static void free_rerere_dirs(void)
34+
{
35+
int i;
36+
for (i = 0; i < rerere_dir_nr; i++)
37+
free(rerere_dir[i]);
38+
free(rerere_dir);
39+
rerere_dir_nr = rerere_dir_alloc = 0;
40+
rerere_dir = NULL;
41+
}
42+
2543
static void free_rerere_id(struct string_list_item *item)
2644
{
2745
free(item->util);
2846
}
2947

3048
static const char *rerere_id_hex(const struct rerere_id *id)
3149
{
32-
return id->hex;
50+
return sha1_to_hex(id->collection->sha1);
3351
}
3452

3553
const char *rerere_path(const struct rerere_id *id, const char *file)
@@ -40,6 +58,37 @@ const char *rerere_path(const struct rerere_id *id, const char *file)
4058
return git_path("rr-cache/%s/%s", rerere_id_hex(id), file);
4159
}
4260

61+
static const unsigned char *rerere_dir_sha1(size_t i, void *table)
62+
{
63+
struct rerere_dir **rr_dir = table;
64+
return rr_dir[i]->sha1;
65+
}
66+
67+
static struct rerere_dir *find_rerere_dir(const char *hex)
68+
{
69+
unsigned char sha1[20];
70+
struct rerere_dir *rr_dir;
71+
int pos;
72+
73+
if (get_sha1_hex(hex, sha1))
74+
return NULL; /* BUG */
75+
pos = sha1_pos(sha1, rerere_dir, rerere_dir_nr, rerere_dir_sha1);
76+
if (pos < 0) {
77+
rr_dir = xmalloc(sizeof(*rr_dir));
78+
hashcpy(rr_dir->sha1, sha1);
79+
pos = -1 - pos;
80+
81+
/* Make sure the array is big enough ... */
82+
ALLOC_GROW(rerere_dir, rerere_dir_nr + 1, rerere_dir_alloc);
83+
/* ... and add it in. */
84+
rerere_dir_nr++;
85+
memmove(rerere_dir + pos + 1, rerere_dir + pos,
86+
(rerere_dir_nr - pos - 1) * sizeof(*rerere_dir));
87+
rerere_dir[pos] = rr_dir;
88+
}
89+
return rerere_dir[pos];
90+
}
91+
4392
static int has_rerere_resolution(const struct rerere_id *id)
4493
{
4594
struct stat st;
@@ -50,7 +99,7 @@ static int has_rerere_resolution(const struct rerere_id *id)
5099
static struct rerere_id *new_rerere_id_hex(char *hex)
51100
{
52101
struct rerere_id *id = xmalloc(sizeof(*id));
53-
xsnprintf(id->hex, sizeof(id->hex), "%s", hex);
102+
id->collection = find_rerere_dir(hex);
54103
return id;
55104
}
56105

@@ -810,12 +859,14 @@ int setup_rerere(struct string_list *merge_rr, int flags)
810859
int rerere(int flags)
811860
{
812861
struct string_list merge_rr = STRING_LIST_INIT_DUP;
813-
int fd;
862+
int fd, status;
814863

815864
fd = setup_rerere(&merge_rr, flags);
816865
if (fd < 0)
817866
return 0;
818-
return do_plain_rerere(&merge_rr, fd);
867+
status = do_plain_rerere(&merge_rr, fd);
868+
free_rerere_dirs();
869+
return status;
819870
}
820871

821872
static int rerere_forget_one_path(const char *path, struct string_list *rr)
@@ -900,7 +951,7 @@ int rerere_forget(struct pathspec *pathspec)
900951
static struct rerere_id *dirname_to_id(const char *name)
901952
{
902953
static struct rerere_id id;
903-
xsnprintf(id.hex, sizeof(id.hex), "%s", name);
954+
id.collection = find_rerere_dir(name);
904955
return &id;
905956
}
906957

rerere.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ struct pathspec;
1515
*/
1616
extern void *RERERE_RESOLVED;
1717

18+
struct rerere_dir;
1819
struct rerere_id {
19-
char hex[41];
20+
struct rerere_dir *collection;
2021
};
2122

2223
extern int setup_rerere(struct string_list *, int);

0 commit comments

Comments
 (0)