99#include "pack.h"
1010#include "csum-file.h"
1111#include "tree-walk.h"
12+ #include "diff.h"
13+ #include "revision.h"
14+ #include "list-objects.h"
1215#include <sys/time.h>
1316#include <signal.h>
1417
15- static const char pack_usage [] = "git-pack-objects [-q] [--no-reuse-delta] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list" ;
18+ static const char pack_usage [] = "git-pack-objects [-q] [--no-reuse-delta] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} [--revs [--unpacked | --all]* <ref-list | < object-list] " ;
1619
1720struct object_entry {
1821 unsigned char sha1 [20 ];
@@ -1326,89 +1329,14 @@ static int git_pack_config(const char *k, const char *v)
13261329 return git_default_config (k , v );
13271330}
13281331
1329- int cmd_pack_objects ( int argc , const char * * argv , const char * prefix )
1332+ static void read_object_list_from_stdin ( void )
13301333{
1331- SHA_CTX ctx ;
1332- char line [40 + 1 + PATH_MAX + 2 ];
1333- int depth = 10 ;
1334- struct object_entry * * list ;
13351334 int num_preferred_base = 0 ;
1336- int i ;
1337-
1338- git_config (git_pack_config );
1339-
1340- progress = isatty (2 );
1341- for (i = 1 ; i < argc ; i ++ ) {
1342- const char * arg = argv [i ];
1343-
1344- if (* arg == '-' ) {
1345- if (!strcmp ("--non-empty" , arg )) {
1346- non_empty = 1 ;
1347- continue ;
1348- }
1349- if (!strcmp ("--local" , arg )) {
1350- local = 1 ;
1351- continue ;
1352- }
1353- if (!strcmp ("--progress" , arg )) {
1354- progress = 1 ;
1355- continue ;
1356- }
1357- if (!strcmp ("--incremental" , arg )) {
1358- incremental = 1 ;
1359- continue ;
1360- }
1361- if (!strncmp ("--window=" , arg , 9 )) {
1362- char * end ;
1363- window = strtoul (arg + 9 , & end , 0 );
1364- if (!arg [9 ] || * end )
1365- usage (pack_usage );
1366- continue ;
1367- }
1368- if (!strncmp ("--depth=" , arg , 8 )) {
1369- char * end ;
1370- depth = strtoul (arg + 8 , & end , 0 );
1371- if (!arg [8 ] || * end )
1372- usage (pack_usage );
1373- continue ;
1374- }
1375- if (!strcmp ("--progress" , arg )) {
1376- progress = 1 ;
1377- continue ;
1378- }
1379- if (!strcmp ("-q" , arg )) {
1380- progress = 0 ;
1381- continue ;
1382- }
1383- if (!strcmp ("--no-reuse-delta" , arg )) {
1384- no_reuse_delta = 1 ;
1385- continue ;
1386- }
1387- if (!strcmp ("--stdout" , arg )) {
1388- pack_to_stdout = 1 ;
1389- continue ;
1390- }
1391- usage (pack_usage );
1392- }
1393- if (base_name )
1394- usage (pack_usage );
1395- base_name = arg ;
1396- }
1397-
1398- if (pack_to_stdout != !base_name )
1399- usage (pack_usage );
1400-
1401- prepare_packed_git ();
1402-
1403- if (progress ) {
1404- fprintf (stderr , "Generating pack...\n" );
1405- setup_progress_signal ();
1406- }
1335+ char line [40 + 1 + PATH_MAX + 2 ];
1336+ unsigned char sha1 [20 ];
1337+ unsigned hash ;
14071338
14081339 for (;;) {
1409- unsigned char sha1 [20 ];
1410- unsigned hash ;
1411-
14121340 if (!fgets (line , sizeof (line ), stdin )) {
14131341 if (feof (stdin ))
14141342 break ;
@@ -1419,21 +1347,226 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
14191347 clearerr (stdin );
14201348 continue ;
14211349 }
1422-
14231350 if (line [0 ] == '-' ) {
14241351 if (get_sha1_hex (line + 1 , sha1 ))
14251352 die ("expected edge sha1, got garbage:\n %s" ,
1426- line + 1 );
1353+ line );
14271354 if (num_preferred_base ++ < window )
14281355 add_preferred_base (sha1 );
14291356 continue ;
14301357 }
14311358 if (get_sha1_hex (line , sha1 ))
14321359 die ("expected sha1, got garbage:\n %s" , line );
1360+
14331361 hash = name_hash (line + 41 );
14341362 add_preferred_base_object (line + 41 , hash );
14351363 add_object_entry (sha1 , hash , 0 );
14361364 }
1365+ }
1366+
1367+ /* copied from rev-list but needs to do things slightly differently */
1368+ static void mark_edge_parents_uninteresting (struct commit * commit )
1369+ {
1370+ struct commit_list * parents ;
1371+
1372+ for (parents = commit -> parents ; parents ; parents = parents -> next ) {
1373+ struct commit * parent = parents -> item ;
1374+ if (!(parent -> object .flags & UNINTERESTING ))
1375+ continue ;
1376+ mark_tree_uninteresting (parent -> tree );
1377+ }
1378+ }
1379+
1380+ static void mark_edges_uninteresting (struct commit_list * list )
1381+ {
1382+ for ( ; list ; list = list -> next ) {
1383+ struct commit * commit = list -> item ;
1384+
1385+ if (commit -> object .flags & UNINTERESTING ) {
1386+ mark_tree_uninteresting (commit -> tree );
1387+ continue ;
1388+ }
1389+ mark_edge_parents_uninteresting (commit );
1390+ }
1391+ }
1392+
1393+ static void show_commit (struct commit * commit )
1394+ {
1395+ unsigned hash = name_hash ("" );
1396+ add_object_entry (commit -> object .sha1 , hash , 0 );
1397+ }
1398+
1399+ static void show_object (struct object_array_entry * p )
1400+ {
1401+ unsigned hash = name_hash (p -> name );
1402+ add_object_entry (p -> item -> sha1 , hash , 0 );
1403+ }
1404+
1405+ static void get_object_list (int unpacked , int all )
1406+ {
1407+ struct rev_info revs ;
1408+ char line [1000 ];
1409+ const char * av [6 ];
1410+ int ac ;
1411+ int flags = 0 ;
1412+
1413+ av [0 ] = "pack-objects" ;
1414+ av [1 ] = "--objects" ;
1415+ ac = 2 ;
1416+ if (unpacked )
1417+ av [ac ++ ] = "--unpacked" ;
1418+ if (all )
1419+ av [ac ++ ] = "--all" ;
1420+ av [ac ++ ] = "--stdin" ;
1421+ av [ac ] = NULL ;
1422+
1423+ init_revisions (& revs , NULL );
1424+ save_commit_buffer = 0 ;
1425+ track_object_refs = 0 ;
1426+ setup_revisions (ac , av , & revs , NULL );
1427+
1428+ /* make sure we did not get pathspecs */
1429+ if (revs .prune_data )
1430+ die ("pathspec given" );
1431+
1432+ while (fgets (line , sizeof (line ), stdin ) != NULL ) {
1433+ int len = strlen (line );
1434+ if (line [len - 1 ] == '\n' )
1435+ line [-- len ] = 0 ;
1436+ if (!len )
1437+ break ;
1438+ if (* line == '-' ) {
1439+ if (!strcmp (line , "--not" )) {
1440+ flags ^= UNINTERESTING ;
1441+ continue ;
1442+ }
1443+ die ("not a rev '%s'" , line );
1444+ }
1445+ if (handle_revision_arg (line , & revs , flags , 1 ))
1446+ die ("bad revision '%s'" , line );
1447+ }
1448+
1449+ prepare_revision_walk (& revs );
1450+ mark_edges_uninteresting (revs .commits );
1451+
1452+ traverse_commit_list (& revs , show_commit , show_object );
1453+ }
1454+
1455+ int cmd_pack_objects (int argc , const char * * argv , const char * prefix )
1456+ {
1457+ SHA_CTX ctx ;
1458+ int depth = 10 ;
1459+ struct object_entry * * list ;
1460+ int use_internal_rev_list = 0 ;
1461+ int unpacked = 0 ;
1462+ int all = 0 ;
1463+ int i ;
1464+
1465+ git_config (git_pack_config );
1466+
1467+ progress = isatty (2 );
1468+ for (i = 1 ; i < argc ; i ++ ) {
1469+ const char * arg = argv [i ];
1470+
1471+ if (* arg != '-' )
1472+ break ;
1473+
1474+ if (!strcmp ("--non-empty" , arg )) {
1475+ non_empty = 1 ;
1476+ continue ;
1477+ }
1478+ if (!strcmp ("--local" , arg )) {
1479+ local = 1 ;
1480+ continue ;
1481+ }
1482+ if (!strcmp ("--progress" , arg )) {
1483+ progress = 1 ;
1484+ continue ;
1485+ }
1486+ if (!strcmp ("--incremental" , arg )) {
1487+ incremental = 1 ;
1488+ continue ;
1489+ }
1490+ if (!strncmp ("--window=" , arg , 9 )) {
1491+ char * end ;
1492+ window = strtoul (arg + 9 , & end , 0 );
1493+ if (!arg [9 ] || * end )
1494+ usage (pack_usage );
1495+ continue ;
1496+ }
1497+ if (!strncmp ("--depth=" , arg , 8 )) {
1498+ char * end ;
1499+ depth = strtoul (arg + 8 , & end , 0 );
1500+ if (!arg [8 ] || * end )
1501+ usage (pack_usage );
1502+ continue ;
1503+ }
1504+ if (!strcmp ("--progress" , arg )) {
1505+ progress = 1 ;
1506+ continue ;
1507+ }
1508+ if (!strcmp ("-q" , arg )) {
1509+ progress = 0 ;
1510+ continue ;
1511+ }
1512+ if (!strcmp ("--no-reuse-delta" , arg )) {
1513+ no_reuse_delta = 1 ;
1514+ continue ;
1515+ }
1516+ if (!strcmp ("--stdout" , arg )) {
1517+ pack_to_stdout = 1 ;
1518+ continue ;
1519+ }
1520+ if (!strcmp ("--revs" , arg )) {
1521+ use_internal_rev_list = 1 ;
1522+ continue ;
1523+ }
1524+ if (!strcmp ("--unpacked" , arg )) {
1525+ unpacked = 1 ;
1526+ continue ;
1527+ }
1528+ if (!strcmp ("--all" , arg )) {
1529+ all = 1 ;
1530+ continue ;
1531+ }
1532+ usage (pack_usage );
1533+ }
1534+
1535+ /* Traditionally "pack-objects [options] base extra" failed;
1536+ * we would however want to take refs parameter that would
1537+ * have been given to upstream rev-list ourselves, which means
1538+ * we somehow want to say what the base name is. So the
1539+ * syntax would be:
1540+ *
1541+ * pack-objects [options] base <refs...>
1542+ *
1543+ * in other words, we would treat the first non-option as the
1544+ * base_name and send everything else to the internal revision
1545+ * walker.
1546+ */
1547+
1548+ if (!pack_to_stdout )
1549+ base_name = argv [i ++ ];
1550+
1551+ if (pack_to_stdout != !base_name )
1552+ usage (pack_usage );
1553+
1554+ /* --unpacked and --all makes sense only with --revs */
1555+ if (!use_internal_rev_list && (unpacked || all ))
1556+ usage (pack_usage );
1557+
1558+ prepare_packed_git ();
1559+
1560+ if (progress ) {
1561+ fprintf (stderr , "Generating pack...\n" );
1562+ setup_progress_signal ();
1563+ }
1564+
1565+ if (!use_internal_rev_list )
1566+ read_object_list_from_stdin ();
1567+ else
1568+ get_object_list (unpacked , all );
1569+
14371570 if (progress )
14381571 fprintf (stderr , "Done counting %d objects.\n" , nr_objects );
14391572 sorted_by_sha = create_final_object_list ();
0 commit comments