@@ -1427,15 +1427,60 @@ static int check_repositoryformatversion(int *version, git_config *config)
14271427 return 0 ;
14281428}
14291429
1430+ static const char * builtin_extensions [] = {
1431+ "noop"
1432+ };
1433+
1434+ static git_vector user_extensions = GIT_VECTOR_INIT ;
1435+
14301436static int check_valid_extension (const git_config_entry * entry , void * payload )
14311437{
1438+ git_buf cfg = GIT_BUF_INIT ;
1439+ bool reject ;
1440+ const char * extension ;
1441+ size_t i ;
1442+ int error = 0 ;
1443+
14321444 GIT_UNUSED (payload );
14331445
1434- if (!strcmp (entry -> name , "extensions.noop" ))
1435- return 0 ;
1446+ git_vector_foreach (& user_extensions , i , extension ) {
1447+ git_buf_clear (& cfg );
1448+
1449+ /*
1450+ * Users can specify that they don't want to support an
1451+ * extension with a '!' prefix.
1452+ */
1453+ if ((reject = (extension [0 ] == '!' )) == true)
1454+ extension = & extension [1 ];
1455+
1456+ if ((error = git_buf_printf (& cfg , "extensions.%s" , extension )) < 0 )
1457+ goto done ;
14361458
1459+ if (strcmp (entry -> name , cfg .ptr ) == 0 ) {
1460+ if (reject )
1461+ goto fail ;
1462+
1463+ goto done ;
1464+ }
1465+ }
1466+
1467+ for (i = 0 ; i < ARRAY_SIZE (builtin_extensions ); i ++ ) {
1468+ extension = builtin_extensions [i ];
1469+
1470+ if ((error = git_buf_printf (& cfg , "extensions.%s" , extension )) < 0 )
1471+ goto done ;
1472+
1473+ if (strcmp (entry -> name , cfg .ptr ) == 0 )
1474+ goto done ;
1475+ }
1476+
1477+ fail :
14371478 git_error_set (GIT_ERROR_REPOSITORY , "unsupported extension name %s" , entry -> name );
1438- return -1 ;
1479+ error = -1 ;
1480+
1481+ done :
1482+ git_buf_dispose (& cfg );
1483+ return error ;
14391484}
14401485
14411486static int check_extensions (git_config * config , int version )
@@ -1446,6 +1491,70 @@ static int check_extensions(git_config *config, int version)
14461491 return git_config_foreach_match (config , "^extensions\\." , check_valid_extension , NULL );
14471492}
14481493
1494+ int git_repository__extensions (char * * * out , size_t * out_len )
1495+ {
1496+ git_vector extensions ;
1497+ const char * builtin , * user ;
1498+ char * extension ;
1499+ size_t i , j ;
1500+
1501+ if (git_vector_init (& extensions , 8 , NULL ) < 0 )
1502+ return -1 ;
1503+
1504+ for (i = 0 ; i < ARRAY_SIZE (builtin_extensions ); i ++ ) {
1505+ bool match = false;
1506+
1507+ builtin = builtin_extensions [i ];
1508+
1509+ git_vector_foreach (& user_extensions , j , user ) {
1510+ if (user [0 ] == '!' && strcmp (builtin , & user [1 ]) == 0 ) {
1511+ match = true;
1512+ break ;
1513+ }
1514+ }
1515+
1516+ if (match )
1517+ continue ;
1518+
1519+ if ((extension = git__strdup (builtin )) == NULL ||
1520+ git_vector_insert (& extensions , extension ) < 0 )
1521+ return -1 ;
1522+ }
1523+
1524+ git_vector_foreach (& user_extensions , i , user ) {
1525+ if (user [0 ] == '!' )
1526+ continue ;
1527+
1528+ if ((extension = git__strdup (user )) == NULL ||
1529+ git_vector_insert (& extensions , extension ) < 0 )
1530+ return -1 ;
1531+ }
1532+
1533+ * out = (char * * )git_vector_detach (out_len , NULL , & extensions );
1534+ return 0 ;
1535+ }
1536+
1537+ int git_repository__set_extensions (const char * * extensions , size_t len )
1538+ {
1539+ char * extension ;
1540+ size_t i ;
1541+
1542+ git_repository__free_extensions ();
1543+
1544+ for (i = 0 ; i < len ; i ++ ) {
1545+ if ((extension = git__strdup (extensions [i ])) == NULL ||
1546+ git_vector_insert (& user_extensions , extension ) < 0 )
1547+ return -1 ;
1548+ }
1549+
1550+ return 0 ;
1551+ }
1552+
1553+ void git_repository__free_extensions (void )
1554+ {
1555+ git_vector_free_deep (& user_extensions );
1556+ }
1557+
14491558int git_repository_create_head (const char * git_dir , const char * ref_name )
14501559{
14511560 git_buf ref_path = GIT_BUF_INIT ;
0 commit comments