Skip to content

Commit c566ea1

Browse files
committed
Merge branch 'jc/merge-blobs'
Update the disused merge-tree proof-of-concept code. * jc/merge-blobs: merge-tree: fix d/f conflicts merge-tree: add comments to clarify what these functions are doing merge-tree: lose unused "resolve_directories" merge-tree: lose unused "flags" from merge_list Which merge_file() function do you mean?
2 parents 98294e9 + 35ffe75 commit c566ea1

File tree

8 files changed

+117
-50
lines changed

8 files changed

+117
-50
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ LIB_OBJS += log-tree.o
766766
LIB_OBJS += mailmap.o
767767
LIB_OBJS += match-trees.o
768768
LIB_OBJS += merge.o
769-
LIB_OBJS += merge-file.o
769+
LIB_OBJS += merge-blobs.o
770770
LIB_OBJS += merge-recursive.o
771771
LIB_OBJS += mergesort.o
772772
LIB_OBJS += name-hash.o

builtin/merge-index.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static int merge_entry(int pos, const char *path)
4242
return found;
4343
}
4444

45-
static void merge_file(const char *path)
45+
static void merge_one_path(const char *path)
4646
{
4747
int pos = cache_name_pos(path, strlen(path));
4848

@@ -102,7 +102,7 @@ int cmd_merge_index(int argc, const char **argv, const char *prefix)
102102
}
103103
die("git merge-index: unknown option %s", arg);
104104
}
105-
merge_file(arg);
105+
merge_one_path(arg);
106106
}
107107
if (err && !quiet)
108108
die("merge program failed");

builtin/merge-tree.c

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@
33
#include "xdiff-interface.h"
44
#include "blob.h"
55
#include "exec_cmd.h"
6-
#include "merge-file.h"
6+
#include "merge-blobs.h"
77

88
static const char merge_tree_usage[] = "git merge-tree <base-tree> <branch1> <branch2>";
9-
static int resolve_directories = 1;
109

1110
struct merge_list {
1211
struct merge_list *next;
1312
struct merge_list *link; /* other stages for this object */
1413

15-
unsigned int stage : 2,
16-
flags : 30;
14+
unsigned int stage : 2;
1715
unsigned int mode;
1816
const char *path;
1917
struct blob *blob;
@@ -27,7 +25,7 @@ static void add_merge_entry(struct merge_list *entry)
2725
merge_result_end = &entry->next;
2826
}
2927

30-
static void merge_trees(struct tree_desc t[3], const char *base);
28+
static void merge_trees_recursive(struct tree_desc t[3], const char *base, int df_conflict);
3129

3230
static const char *explanation(struct merge_list *entry)
3331
{
@@ -76,7 +74,7 @@ static void *result(struct merge_list *entry, unsigned long *size)
7674
their = NULL;
7775
if (entry)
7876
their = entry->blob;
79-
return merge_file(path, base, our, their, size);
77+
return merge_blobs(path, base, our, their, size);
8078
}
8179

8280
static void *origin(struct merge_list *entry, unsigned long *size)
@@ -174,52 +172,53 @@ static char *traverse_path(const struct traverse_info *info, const struct name_e
174172
return make_traverse_path(path, info, n);
175173
}
176174

177-
static void resolve(const struct traverse_info *info, struct name_entry *branch1, struct name_entry *result)
175+
static void resolve(const struct traverse_info *info, struct name_entry *ours, struct name_entry *result)
178176
{
179177
struct merge_list *orig, *final;
180178
const char *path;
181179

182-
/* If it's already branch1, don't bother showing it */
183-
if (!branch1)
180+
/* If it's already ours, don't bother showing it */
181+
if (!ours)
184182
return;
185183

186184
path = traverse_path(info, result);
187-
orig = create_entry(2, branch1->mode, branch1->sha1, path);
185+
orig = create_entry(2, ours->mode, ours->sha1, path);
188186
final = create_entry(0, result->mode, result->sha1, path);
189187

190188
final->link = orig;
191189

192190
add_merge_entry(final);
193191
}
194192

195-
static int unresolved_directory(const struct traverse_info *info, struct name_entry n[3])
193+
static void unresolved_directory(const struct traverse_info *info, struct name_entry n[3],
194+
int df_conflict)
196195
{
197196
char *newbase;
198197
struct name_entry *p;
199198
struct tree_desc t[3];
200199
void *buf0, *buf1, *buf2;
201200

202-
if (!resolve_directories)
203-
return 0;
204-
p = n;
205-
if (!p->mode) {
206-
p++;
207-
if (!p->mode)
208-
p++;
201+
for (p = n; p < n + 3; p++) {
202+
if (p->mode && S_ISDIR(p->mode))
203+
break;
209204
}
210-
if (!S_ISDIR(p->mode))
211-
return 0;
205+
if (n + 3 <= p)
206+
return; /* there is no tree here */
207+
212208
newbase = traverse_path(info, p);
213-
buf0 = fill_tree_descriptor(t+0, n[0].sha1);
214-
buf1 = fill_tree_descriptor(t+1, n[1].sha1);
215-
buf2 = fill_tree_descriptor(t+2, n[2].sha1);
216-
merge_trees(t, newbase);
209+
210+
#define ENTRY_SHA1(e) (((e)->mode && S_ISDIR((e)->mode)) ? (e)->sha1 : NULL)
211+
buf0 = fill_tree_descriptor(t+0, ENTRY_SHA1(n + 0));
212+
buf1 = fill_tree_descriptor(t+1, ENTRY_SHA1(n + 1));
213+
buf2 = fill_tree_descriptor(t+2, ENTRY_SHA1(n + 2));
214+
#undef ENTRY_SHA1
215+
216+
merge_trees_recursive(t, newbase, df_conflict);
217217

218218
free(buf0);
219219
free(buf1);
220220
free(buf2);
221221
free(newbase);
222-
return 1;
223222
}
224223

225224

@@ -242,18 +241,26 @@ static struct merge_list *link_entry(unsigned stage, const struct traverse_info
242241
static void unresolved(const struct traverse_info *info, struct name_entry n[3])
243242
{
244243
struct merge_list *entry = NULL;
244+
int i;
245+
unsigned dirmask = 0, mask = 0;
246+
247+
for (i = 0; i < 3; i++) {
248+
mask |= (1 << 1);
249+
if (n[i].mode && S_ISDIR(n[i].mode))
250+
dirmask |= (1 << i);
251+
}
245252

246-
if (unresolved_directory(info, n))
253+
unresolved_directory(info, n, dirmask && (dirmask != mask));
254+
255+
if (dirmask == mask)
247256
return;
248257

249-
/*
250-
* Do them in reverse order so that the resulting link
251-
* list has the stages in order - link_entry adds new
252-
* links at the front.
253-
*/
254-
entry = link_entry(3, info, n + 2, entry);
255-
entry = link_entry(2, info, n + 1, entry);
256-
entry = link_entry(1, info, n + 0, entry);
258+
if (n[2].mode && !S_ISDIR(n[2].mode))
259+
entry = link_entry(3, info, n + 2, entry);
260+
if (n[1].mode && !S_ISDIR(n[1].mode))
261+
entry = link_entry(2, info, n + 1, entry);
262+
if (n[0].mode && !S_ISDIR(n[0].mode))
263+
entry = link_entry(1, info, n + 0, entry);
257264

258265
add_merge_entry(entry);
259266
}
@@ -292,20 +299,29 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
292299
/* Same in both? */
293300
if (same_entry(entry+1, entry+2)) {
294301
if (entry[0].sha1) {
302+
/* Modified identically */
295303
resolve(info, NULL, entry+1);
296304
return mask;
297305
}
306+
/* "Both added the same" is left unresolved */
298307
}
299308

300309
if (same_entry(entry+0, entry+1)) {
301310
if (entry[2].sha1 && !S_ISDIR(entry[2].mode)) {
311+
/* We did not touch, they modified -- take theirs */
302312
resolve(info, entry+1, entry+2);
303313
return mask;
304314
}
315+
/*
316+
* If we did not touch a directory but they made it
317+
* into a file, we fall through and unresolved()
318+
* recurses down. Likewise for the opposite case.
319+
*/
305320
}
306321

307322
if (same_entry(entry+0, entry+2)) {
308323
if (entry[1].sha1 && !S_ISDIR(entry[1].mode)) {
324+
/* We modified, they did not touch -- take ours */
309325
resolve(info, NULL, entry+1);
310326
return mask;
311327
}
@@ -315,15 +331,21 @@ static int threeway_callback(int n, unsigned long mask, unsigned long dirmask, s
315331
return mask;
316332
}
317333

318-
static void merge_trees(struct tree_desc t[3], const char *base)
334+
static void merge_trees_recursive(struct tree_desc t[3], const char *base, int df_conflict)
319335
{
320336
struct traverse_info info;
321337

322338
setup_traverse_info(&info, base);
339+
info.data = &df_conflict;
323340
info.fn = threeway_callback;
324341
traverse_trees(3, t, &info);
325342
}
326343

344+
static void merge_trees(struct tree_desc t[3], const char *base)
345+
{
346+
merge_trees_recursive(t, base, 0);
347+
}
348+
327349
static void *get_tree_descriptor(struct tree_desc *desc, const char *rev)
328350
{
329351
unsigned char sha1[20];

merge-file.c renamed to merge-blobs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include "xdiff-interface.h"
44
#include "ll-merge.h"
55
#include "blob.h"
6-
#include "merge-file.h"
6+
#include "merge-blobs.h"
77

88
static int fill_mmfile_blob(mmfile_t *f, struct blob *obj)
99
{
@@ -80,7 +80,7 @@ static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2)
8080
return xdi_diff(f1, f2, &xpp, &xecfg, &ecb);
8181
}
8282

83-
void *merge_file(const char *path, struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
83+
void *merge_blobs(const char *path, struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
8484
{
8585
void *res = NULL;
8686
mmfile_t f1, f2, common;

merge-blobs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef MERGE_BLOBS_H
2+
#define MERGE_BLOBS_H
3+
4+
#include "blob.h"
5+
6+
extern void *merge_blobs(const char *, struct blob *, struct blob *, struct blob *, unsigned long *);
7+
8+
#endif /* MERGE_BLOBS_H */

merge-file.h

Lines changed: 0 additions & 7 deletions
This file was deleted.

merge-recursive.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,7 @@ merge_file_special_markers(struct merge_options *o,
976976
return mfi;
977977
}
978978

979-
static struct merge_file_info merge_file(struct merge_options *o,
979+
static struct merge_file_info merge_file_one(struct merge_options *o,
980980
const char *path,
981981
const unsigned char *o_sha, int o_mode,
982982
const unsigned char *a_sha, int a_mode,
@@ -1166,7 +1166,7 @@ static void conflict_rename_rename_1to2(struct merge_options *o,
11661166
struct merge_file_info mfi;
11671167
struct diff_filespec other;
11681168
struct diff_filespec *add;
1169-
mfi = merge_file(o, one->path,
1169+
mfi = merge_file_one(o, one->path,
11701170
one->sha1, one->mode,
11711171
a->sha1, a->mode,
11721172
b->sha1, b->mode,
@@ -1450,7 +1450,7 @@ static int process_renames(struct merge_options *o,
14501450
ren1_dst, branch2);
14511451
if (o->call_depth) {
14521452
struct merge_file_info mfi;
1453-
mfi = merge_file(o, ren1_dst, null_sha1, 0,
1453+
mfi = merge_file_one(o, ren1_dst, null_sha1, 0,
14541454
ren1->pair->two->sha1, ren1->pair->two->mode,
14551455
dst_other.sha1, dst_other.mode,
14561456
branch1, branch2);

t/t4300-merge-tree.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,48 @@ EXPECTED
254254
test_cmp expected actual
255255
'
256256

257+
test_expect_success 'turn file to tree' '
258+
git reset --hard initial &&
259+
rm initial-file &&
260+
mkdir initial-file &&
261+
test_commit "turn-file-to-tree" "initial-file/ONE" "CCC" &&
262+
git merge-tree initial initial turn-file-to-tree >actual &&
263+
cat >expect <<-\EOF &&
264+
added in remote
265+
their 100644 43aa4fdec31eb92e1fdc2f0ce6ea9ddb7c32bcf7 initial-file/ONE
266+
@@ -0,0 +1 @@
267+
+CCC
268+
removed in remote
269+
base 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file
270+
our 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file
271+
@@ -1 +0,0 @@
272+
-initial
273+
EOF
274+
test_cmp expect actual
275+
'
276+
277+
test_expect_success 'turn tree to file' '
278+
git reset --hard initial &&
279+
mkdir dir &&
280+
test_commit "add-tree" "dir/path" "AAA" &&
281+
test_commit "add-another-tree" "dir/another" "BBB" &&
282+
rm -fr dir &&
283+
test_commit "make-file" "dir" "CCC" &&
284+
git merge-tree add-tree add-another-tree make-file >actual &&
285+
cat >expect <<-\EOF &&
286+
added in local
287+
our 100644 ba629238ca89489f2b350e196ca445e09d8bb834 dir/another
288+
removed in remote
289+
base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d dir/path
290+
our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d dir/path
291+
@@ -1 +0,0 @@
292+
-AAA
293+
added in remote
294+
their 100644 43aa4fdec31eb92e1fdc2f0ce6ea9ddb7c32bcf7 dir
295+
@@ -0,0 +1 @@
296+
+CCC
297+
EOF
298+
test_cmp expect actual
299+
'
300+
257301
test_done

0 commit comments

Comments
 (0)