@@ -170,6 +170,11 @@ Format of STDIN stream:
170
170
#define DEPTH_BITS 13
171
171
#define MAX_DEPTH ((1<<DEPTH_BITS)-1)
172
172
173
+ /*
174
+ * We abuse the setuid bit on directories to mean "do not delta".
175
+ */
176
+ #define NO_DELTA S_ISUID
177
+
173
178
struct object_entry {
174
179
struct pack_idx_entry idx ;
175
180
struct object_entry * next ;
@@ -1416,8 +1421,9 @@ static void mktree(struct tree_content *t, int v, struct strbuf *b)
1416
1421
struct tree_entry * e = t -> entries [i ];
1417
1422
if (!e -> versions [v ].mode )
1418
1423
continue ;
1419
- strbuf_addf (b , "%o %s%c" , (unsigned int )e -> versions [v ].mode ,
1420
- e -> name -> str_dat , '\0' );
1424
+ strbuf_addf (b , "%o %s%c" ,
1425
+ (unsigned int )(e -> versions [v ].mode & ~NO_DELTA ),
1426
+ e -> name -> str_dat , '\0' );
1421
1427
strbuf_add (b , e -> versions [v ].sha1 , 20 );
1422
1428
}
1423
1429
}
@@ -1427,7 +1433,7 @@ static void store_tree(struct tree_entry *root)
1427
1433
struct tree_content * t = root -> tree ;
1428
1434
unsigned int i , j , del ;
1429
1435
struct last_object lo = { STRBUF_INIT , 0 , 0 , /* no_swap */ 1 };
1430
- struct object_entry * le ;
1436
+ struct object_entry * le = NULL ;
1431
1437
1432
1438
if (!is_null_sha1 (root -> versions [1 ].sha1 ))
1433
1439
return ;
@@ -1437,7 +1443,8 @@ static void store_tree(struct tree_entry *root)
1437
1443
store_tree (t -> entries [i ]);
1438
1444
}
1439
1445
1440
- le = find_object (root -> versions [0 ].sha1 );
1446
+ if (!(root -> versions [0 ].mode & NO_DELTA ))
1447
+ le = find_object (root -> versions [0 ].sha1 );
1441
1448
if (S_ISDIR (root -> versions [0 ].mode ) && le && le -> pack_id == pack_id ) {
1442
1449
mktree (t , 0 , & old_tree );
1443
1450
lo .data = old_tree ;
@@ -1471,6 +1478,7 @@ static void tree_content_replace(
1471
1478
{
1472
1479
if (!S_ISDIR (mode ))
1473
1480
die ("Root cannot be a non-directory" );
1481
+ hashclr (root -> versions [0 ].sha1 );
1474
1482
hashcpy (root -> versions [1 ].sha1 , sha1 );
1475
1483
if (root -> tree )
1476
1484
release_tree_content_recursive (root -> tree );
@@ -1515,6 +1523,23 @@ static int tree_content_set(
1515
1523
if (e -> tree )
1516
1524
release_tree_content_recursive (e -> tree );
1517
1525
e -> tree = subtree ;
1526
+
1527
+ /*
1528
+ * We need to leave e->versions[0].sha1 alone
1529
+ * to avoid modifying the preimage tree used
1530
+ * when writing out the parent directory.
1531
+ * But after replacing the subdir with a
1532
+ * completely different one, it's not a good
1533
+ * delta base any more, and besides, we've
1534
+ * thrown away the tree entries needed to
1535
+ * make a delta against it.
1536
+ *
1537
+ * So let's just explicitly disable deltas
1538
+ * for the subtree.
1539
+ */
1540
+ if (S_ISDIR (e -> versions [0 ].mode ))
1541
+ e -> versions [0 ].mode |= NO_DELTA ;
1542
+
1518
1543
hashclr (root -> versions [1 ].sha1 );
1519
1544
return 1 ;
1520
1545
}
@@ -2938,7 +2963,7 @@ static void print_ls(int mode, const unsigned char *sha1, const char *path)
2938
2963
/* mode SP type SP object_name TAB path LF */
2939
2964
strbuf_reset (& line );
2940
2965
strbuf_addf (& line , "%06o %s %s\t" ,
2941
- mode , type , sha1_to_hex (sha1 ));
2966
+ mode & ~ NO_DELTA , type , sha1_to_hex (sha1 ));
2942
2967
quote_c_style (path , & line , NULL , 0 );
2943
2968
strbuf_addch (& line , '\n' );
2944
2969
}
0 commit comments