Fossil SCM
Further enhancements to "fossil git export" to fix a memory leak and to improve the operation of --mainbranch.
Commit
953fac2b9b19692c292e5b2cd4887bfd90210fe8a3d0615ba65dc5de84623285
Parent
aca011c5e5082cc…
1 file changed
+83
-9
+83
-9
| --- src/export.c | ||
| +++ src/export.c | ||
| @@ -1144,10 +1144,11 @@ | ||
| 1144 | 1144 | ** export */ |
| 1145 | 1145 | if( nErr ){ |
| 1146 | 1146 | gitmirror_message(VERB_ERROR, |
| 1147 | 1147 | "export of %s abandoned due to missing files\n", zUuid); |
| 1148 | 1148 | *pnLimit = 0; |
| 1149 | + manifest_destroy(pMan); | |
| 1149 | 1150 | return 1; |
| 1150 | 1151 | } |
| 1151 | 1152 | |
| 1152 | 1153 | /* Figure out which branch this check-in is a member of */ |
| 1153 | 1154 | zBranch = db_text(0, |
| @@ -1271,10 +1272,12 @@ | ||
| 1271 | 1272 | zFNQuoted = gitmirror_quote_filename_if_needed(zFilename); |
| 1272 | 1273 | fprintf(xCmd,"M %s %s %s\n", zGitMode, zMark, zFNQuoted); |
| 1273 | 1274 | fossil_free(zFNQuoted); |
| 1274 | 1275 | } |
| 1275 | 1276 | db_finalize(&q); |
| 1277 | + manifest_destroy(pMan); | |
| 1278 | + pMan = 0; | |
| 1276 | 1279 | |
| 1277 | 1280 | /* Include Fossil-generated auxiliary files in the check-in */ |
| 1278 | 1281 | if( fManifest & MFESTFLG_RAW ){ |
| 1279 | 1282 | Blob manifest; |
| 1280 | 1283 | content_get(rid, &manifest); |
| @@ -1298,10 +1301,78 @@ | ||
| 1298 | 1301 | /* The check-in is finished, so decrement the counter */ |
| 1299 | 1302 | (*pnLimit)--; |
| 1300 | 1303 | return 0; |
| 1301 | 1304 | } |
| 1302 | 1305 | |
| 1306 | +/* | |
| 1307 | +** Create a new Git repository at zMirror to use as the mirror. | |
| 1308 | +** Try to make zMainBr be the main branch for the new repository. | |
| 1309 | +** | |
| 1310 | +** A side-effect of this routine is that current-working directory | |
| 1311 | +** is changed to zMirror. | |
| 1312 | +** | |
| 1313 | +** If zMainBr is initially NULL, then the return value will be the | |
| 1314 | +** name of the default branch to be used by Git. If zMainBr is | |
| 1315 | +** initially non-NULL, then the return value will be a copy of zMainBr. | |
| 1316 | +*/ | |
| 1317 | +static char *gitmirror_init( | |
| 1318 | + const char *zMirror, | |
| 1319 | + char *zMainBr | |
| 1320 | +){ | |
| 1321 | + char *zCmd; | |
| 1322 | + int rc; | |
| 1323 | + | |
| 1324 | + /* Create a new Git repository at zMirror */ | |
| 1325 | + zCmd = mprintf("git init %$", zMirror); | |
| 1326 | + gitmirror_message(VERB_NORMAL, "%s\n", zCmd); | |
| 1327 | + rc = fossil_system(zCmd); | |
| 1328 | + if( rc ){ | |
| 1329 | + fossil_fatal("cannot initialize git repository using: %s\n", zCmd); | |
| 1330 | + } | |
| 1331 | + fossil_free(zCmd); | |
| 1332 | + | |
| 1333 | + /* Must be in the new Git repository directory for subsequent commands */ | |
| 1334 | + rc = file_chdir(zMirror, 0); | |
| 1335 | + if( rc ){ | |
| 1336 | + fossil_fatal("cannot change to directory \"%s\"", zMirror); | |
| 1337 | + } | |
| 1338 | + | |
| 1339 | + if( zMainBr ){ | |
| 1340 | + /* Set the current branch to zMainBr */ | |
| 1341 | + zCmd = mprintf("git symbolic-ref HEAD refs/heads/%s", zMainBr); | |
| 1342 | + gitmirror_message(VERB_NORMAL, "%s\n", zCmd); | |
| 1343 | + rc = fossil_system(zCmd); | |
| 1344 | + if( rc ){ | |
| 1345 | + fossil_fatal("git command failed: %s", zCmd); | |
| 1346 | + } | |
| 1347 | + fossil_free(zCmd); | |
| 1348 | + }else{ | |
| 1349 | + /* If zMainBr is not specified, then check to see what branch | |
| 1350 | + ** name Git chose for itself */ | |
| 1351 | + char *z; | |
| 1352 | + char zLine[1000]; | |
| 1353 | + FILE *xCmd; | |
| 1354 | + int i; | |
| 1355 | + zCmd = "git symbolic-ref --short HEAD"; | |
| 1356 | + gitmirror_message(VERB_NORMAL, "%s\n", zCmd); | |
| 1357 | + xCmd = popen(zCmd, "r"); | |
| 1358 | + if( xCmd==0 ){ | |
| 1359 | + fossil_fatal("git command failed: %s", zCmd); | |
| 1360 | + } | |
| 1361 | + | |
| 1362 | + z = fgets(zLine, sizeof(zLine), xCmd); | |
| 1363 | + pclose(xCmd); | |
| 1364 | + if( z==0 ){ | |
| 1365 | + fossil_fatal("no output from \"%s\"", zCmd); | |
| 1366 | + } | |
| 1367 | + for(i=0; z[i] && !fossil_isspace(z[i]); i++){} | |
| 1368 | + z[i] = 0; | |
| 1369 | + zMainBr = fossil_strdup(z); | |
| 1370 | + } | |
| 1371 | + return zMainBr; | |
| 1372 | +} | |
| 1373 | + | |
| 1303 | 1374 | /* |
| 1304 | 1375 | ** Implementation of the "fossil git export" command. |
| 1305 | 1376 | */ |
| 1306 | 1377 | void gitmirror_export_command(void){ |
| 1307 | 1378 | const char *zLimit; /* Text of the --limit flag */ |
| @@ -1310,11 +1381,11 @@ | ||
| 1310 | 1381 | char *zMirror; /* Name of the mirror */ |
| 1311 | 1382 | char *z; /* Generic string */ |
| 1312 | 1383 | char *zCmd; /* git command to run as a subprocess */ |
| 1313 | 1384 | const char *zDebug = 0; /* Value of the --debug flag */ |
| 1314 | 1385 | const char *zAutoPush = 0; /* Value of the --autopush flag */ |
| 1315 | - const char *zMainBr = 0; /* Value of the --mainbranch flag */ | |
| 1386 | + char *zMainBr = 0; /* Value of the --mainbranch flag */ | |
| 1316 | 1387 | char *zPushUrl; /* URL to sync the mirror to */ |
| 1317 | 1388 | double rEnd; /* time of most recent export */ |
| 1318 | 1389 | int rc; /* Result code */ |
| 1319 | 1390 | int bForce; /* Do the export and sync even if no changes*/ |
| 1320 | 1391 | int bNeedRepack = 0; /* True if we should run repack at the end */ |
| @@ -1331,11 +1402,11 @@ | ||
| 1331 | 1402 | if( zLimit ){ |
| 1332 | 1403 | nLimit = (unsigned int)atoi(zLimit); |
| 1333 | 1404 | if( nLimit<=0 ) fossil_fatal("--limit must be positive"); |
| 1334 | 1405 | } |
| 1335 | 1406 | zAutoPush = find_option("autopush",0,1); |
| 1336 | - zMainBr = find_option("mainbranch",0,1); | |
| 1407 | + zMainBr = (char*)find_option("mainbranch",0,1); | |
| 1337 | 1408 | bForce = find_option("force","f",0)!=0; |
| 1338 | 1409 | bIfExists = find_option("if-mirrored",0,0)!=0; |
| 1339 | 1410 | gitmirror_verbosity = VERB_NORMAL; |
| 1340 | 1411 | while( find_option("quiet","q",0)!=0 ){ gitmirror_verbosity--; } |
| 1341 | 1412 | while( find_option("verbose","v",0)!=0 ){ gitmirror_verbosity++; } |
| @@ -1350,25 +1421,28 @@ | ||
| 1350 | 1421 | zMirror = db_get("last-git-export-repo", 0); |
| 1351 | 1422 | if( zMirror==0 ){ |
| 1352 | 1423 | if( bIfExists ) return; |
| 1353 | 1424 | fossil_fatal("no Git repository specified"); |
| 1354 | 1425 | } |
| 1426 | + | |
| 1427 | + if( zMainBr ){ | |
| 1428 | + z = fossil_strdup(zMainBr); | |
| 1429 | + gitmirror_sanitize_name(z); | |
| 1430 | + if( strcmp(z, zMainBr) ){ | |
| 1431 | + fossil_fatal("\"%s\" is not a legal branch name for Git", zMainBr); | |
| 1432 | + } | |
| 1433 | + fossil_free(z); | |
| 1434 | + } | |
| 1355 | 1435 | |
| 1356 | 1436 | /* Make sure the GIT repository directory exists */ |
| 1357 | 1437 | rc = file_mkdir(zMirror, ExtFILE, 0); |
| 1358 | 1438 | if( rc ) fossil_fatal("cannot create directory \"%s\"", zMirror); |
| 1359 | 1439 | |
| 1360 | 1440 | /* Make sure GIT has been initialized */ |
| 1361 | 1441 | z = mprintf("%s/.git", zMirror); |
| 1362 | 1442 | if( !file_isdir(z, ExtFILE) ){ |
| 1363 | - zCmd = mprintf("git init %$",zMirror); | |
| 1364 | - gitmirror_message(VERB_NORMAL, "%s\n", zCmd); | |
| 1365 | - rc = fossil_system(zCmd); | |
| 1366 | - if( rc ){ | |
| 1367 | - fossil_fatal("cannot initialize the git repository using: \"%s\"", zCmd); | |
| 1368 | - } | |
| 1369 | - fossil_free(zCmd); | |
| 1443 | + zMainBr = gitmirror_init(zMirror, zMainBr); | |
| 1370 | 1444 | bNeedRepack = 1; |
| 1371 | 1445 | } |
| 1372 | 1446 | fossil_free(z); |
| 1373 | 1447 | |
| 1374 | 1448 | /* Make sure the .mirror_state subdirectory exists */ |
| 1375 | 1449 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -1144,10 +1144,11 @@ | |
| 1144 | ** export */ |
| 1145 | if( nErr ){ |
| 1146 | gitmirror_message(VERB_ERROR, |
| 1147 | "export of %s abandoned due to missing files\n", zUuid); |
| 1148 | *pnLimit = 0; |
| 1149 | return 1; |
| 1150 | } |
| 1151 | |
| 1152 | /* Figure out which branch this check-in is a member of */ |
| 1153 | zBranch = db_text(0, |
| @@ -1271,10 +1272,12 @@ | |
| 1271 | zFNQuoted = gitmirror_quote_filename_if_needed(zFilename); |
| 1272 | fprintf(xCmd,"M %s %s %s\n", zGitMode, zMark, zFNQuoted); |
| 1273 | fossil_free(zFNQuoted); |
| 1274 | } |
| 1275 | db_finalize(&q); |
| 1276 | |
| 1277 | /* Include Fossil-generated auxiliary files in the check-in */ |
| 1278 | if( fManifest & MFESTFLG_RAW ){ |
| 1279 | Blob manifest; |
| 1280 | content_get(rid, &manifest); |
| @@ -1298,10 +1301,78 @@ | |
| 1298 | /* The check-in is finished, so decrement the counter */ |
| 1299 | (*pnLimit)--; |
| 1300 | return 0; |
| 1301 | } |
| 1302 | |
| 1303 | /* |
| 1304 | ** Implementation of the "fossil git export" command. |
| 1305 | */ |
| 1306 | void gitmirror_export_command(void){ |
| 1307 | const char *zLimit; /* Text of the --limit flag */ |
| @@ -1310,11 +1381,11 @@ | |
| 1310 | char *zMirror; /* Name of the mirror */ |
| 1311 | char *z; /* Generic string */ |
| 1312 | char *zCmd; /* git command to run as a subprocess */ |
| 1313 | const char *zDebug = 0; /* Value of the --debug flag */ |
| 1314 | const char *zAutoPush = 0; /* Value of the --autopush flag */ |
| 1315 | const char *zMainBr = 0; /* Value of the --mainbranch flag */ |
| 1316 | char *zPushUrl; /* URL to sync the mirror to */ |
| 1317 | double rEnd; /* time of most recent export */ |
| 1318 | int rc; /* Result code */ |
| 1319 | int bForce; /* Do the export and sync even if no changes*/ |
| 1320 | int bNeedRepack = 0; /* True if we should run repack at the end */ |
| @@ -1331,11 +1402,11 @@ | |
| 1331 | if( zLimit ){ |
| 1332 | nLimit = (unsigned int)atoi(zLimit); |
| 1333 | if( nLimit<=0 ) fossil_fatal("--limit must be positive"); |
| 1334 | } |
| 1335 | zAutoPush = find_option("autopush",0,1); |
| 1336 | zMainBr = find_option("mainbranch",0,1); |
| 1337 | bForce = find_option("force","f",0)!=0; |
| 1338 | bIfExists = find_option("if-mirrored",0,0)!=0; |
| 1339 | gitmirror_verbosity = VERB_NORMAL; |
| 1340 | while( find_option("quiet","q",0)!=0 ){ gitmirror_verbosity--; } |
| 1341 | while( find_option("verbose","v",0)!=0 ){ gitmirror_verbosity++; } |
| @@ -1350,25 +1421,28 @@ | |
| 1350 | zMirror = db_get("last-git-export-repo", 0); |
| 1351 | if( zMirror==0 ){ |
| 1352 | if( bIfExists ) return; |
| 1353 | fossil_fatal("no Git repository specified"); |
| 1354 | } |
| 1355 | |
| 1356 | /* Make sure the GIT repository directory exists */ |
| 1357 | rc = file_mkdir(zMirror, ExtFILE, 0); |
| 1358 | if( rc ) fossil_fatal("cannot create directory \"%s\"", zMirror); |
| 1359 | |
| 1360 | /* Make sure GIT has been initialized */ |
| 1361 | z = mprintf("%s/.git", zMirror); |
| 1362 | if( !file_isdir(z, ExtFILE) ){ |
| 1363 | zCmd = mprintf("git init %$",zMirror); |
| 1364 | gitmirror_message(VERB_NORMAL, "%s\n", zCmd); |
| 1365 | rc = fossil_system(zCmd); |
| 1366 | if( rc ){ |
| 1367 | fossil_fatal("cannot initialize the git repository using: \"%s\"", zCmd); |
| 1368 | } |
| 1369 | fossil_free(zCmd); |
| 1370 | bNeedRepack = 1; |
| 1371 | } |
| 1372 | fossil_free(z); |
| 1373 | |
| 1374 | /* Make sure the .mirror_state subdirectory exists */ |
| 1375 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -1144,10 +1144,11 @@ | |
| 1144 | ** export */ |
| 1145 | if( nErr ){ |
| 1146 | gitmirror_message(VERB_ERROR, |
| 1147 | "export of %s abandoned due to missing files\n", zUuid); |
| 1148 | *pnLimit = 0; |
| 1149 | manifest_destroy(pMan); |
| 1150 | return 1; |
| 1151 | } |
| 1152 | |
| 1153 | /* Figure out which branch this check-in is a member of */ |
| 1154 | zBranch = db_text(0, |
| @@ -1271,10 +1272,12 @@ | |
| 1272 | zFNQuoted = gitmirror_quote_filename_if_needed(zFilename); |
| 1273 | fprintf(xCmd,"M %s %s %s\n", zGitMode, zMark, zFNQuoted); |
| 1274 | fossil_free(zFNQuoted); |
| 1275 | } |
| 1276 | db_finalize(&q); |
| 1277 | manifest_destroy(pMan); |
| 1278 | pMan = 0; |
| 1279 | |
| 1280 | /* Include Fossil-generated auxiliary files in the check-in */ |
| 1281 | if( fManifest & MFESTFLG_RAW ){ |
| 1282 | Blob manifest; |
| 1283 | content_get(rid, &manifest); |
| @@ -1298,10 +1301,78 @@ | |
| 1301 | /* The check-in is finished, so decrement the counter */ |
| 1302 | (*pnLimit)--; |
| 1303 | return 0; |
| 1304 | } |
| 1305 | |
| 1306 | /* |
| 1307 | ** Create a new Git repository at zMirror to use as the mirror. |
| 1308 | ** Try to make zMainBr be the main branch for the new repository. |
| 1309 | ** |
| 1310 | ** A side-effect of this routine is that current-working directory |
| 1311 | ** is changed to zMirror. |
| 1312 | ** |
| 1313 | ** If zMainBr is initially NULL, then the return value will be the |
| 1314 | ** name of the default branch to be used by Git. If zMainBr is |
| 1315 | ** initially non-NULL, then the return value will be a copy of zMainBr. |
| 1316 | */ |
| 1317 | static char *gitmirror_init( |
| 1318 | const char *zMirror, |
| 1319 | char *zMainBr |
| 1320 | ){ |
| 1321 | char *zCmd; |
| 1322 | int rc; |
| 1323 | |
| 1324 | /* Create a new Git repository at zMirror */ |
| 1325 | zCmd = mprintf("git init %$", zMirror); |
| 1326 | gitmirror_message(VERB_NORMAL, "%s\n", zCmd); |
| 1327 | rc = fossil_system(zCmd); |
| 1328 | if( rc ){ |
| 1329 | fossil_fatal("cannot initialize git repository using: %s\n", zCmd); |
| 1330 | } |
| 1331 | fossil_free(zCmd); |
| 1332 | |
| 1333 | /* Must be in the new Git repository directory for subsequent commands */ |
| 1334 | rc = file_chdir(zMirror, 0); |
| 1335 | if( rc ){ |
| 1336 | fossil_fatal("cannot change to directory \"%s\"", zMirror); |
| 1337 | } |
| 1338 | |
| 1339 | if( zMainBr ){ |
| 1340 | /* Set the current branch to zMainBr */ |
| 1341 | zCmd = mprintf("git symbolic-ref HEAD refs/heads/%s", zMainBr); |
| 1342 | gitmirror_message(VERB_NORMAL, "%s\n", zCmd); |
| 1343 | rc = fossil_system(zCmd); |
| 1344 | if( rc ){ |
| 1345 | fossil_fatal("git command failed: %s", zCmd); |
| 1346 | } |
| 1347 | fossil_free(zCmd); |
| 1348 | }else{ |
| 1349 | /* If zMainBr is not specified, then check to see what branch |
| 1350 | ** name Git chose for itself */ |
| 1351 | char *z; |
| 1352 | char zLine[1000]; |
| 1353 | FILE *xCmd; |
| 1354 | int i; |
| 1355 | zCmd = "git symbolic-ref --short HEAD"; |
| 1356 | gitmirror_message(VERB_NORMAL, "%s\n", zCmd); |
| 1357 | xCmd = popen(zCmd, "r"); |
| 1358 | if( xCmd==0 ){ |
| 1359 | fossil_fatal("git command failed: %s", zCmd); |
| 1360 | } |
| 1361 | |
| 1362 | z = fgets(zLine, sizeof(zLine), xCmd); |
| 1363 | pclose(xCmd); |
| 1364 | if( z==0 ){ |
| 1365 | fossil_fatal("no output from \"%s\"", zCmd); |
| 1366 | } |
| 1367 | for(i=0; z[i] && !fossil_isspace(z[i]); i++){} |
| 1368 | z[i] = 0; |
| 1369 | zMainBr = fossil_strdup(z); |
| 1370 | } |
| 1371 | return zMainBr; |
| 1372 | } |
| 1373 | |
| 1374 | /* |
| 1375 | ** Implementation of the "fossil git export" command. |
| 1376 | */ |
| 1377 | void gitmirror_export_command(void){ |
| 1378 | const char *zLimit; /* Text of the --limit flag */ |
| @@ -1310,11 +1381,11 @@ | |
| 1381 | char *zMirror; /* Name of the mirror */ |
| 1382 | char *z; /* Generic string */ |
| 1383 | char *zCmd; /* git command to run as a subprocess */ |
| 1384 | const char *zDebug = 0; /* Value of the --debug flag */ |
| 1385 | const char *zAutoPush = 0; /* Value of the --autopush flag */ |
| 1386 | char *zMainBr = 0; /* Value of the --mainbranch flag */ |
| 1387 | char *zPushUrl; /* URL to sync the mirror to */ |
| 1388 | double rEnd; /* time of most recent export */ |
| 1389 | int rc; /* Result code */ |
| 1390 | int bForce; /* Do the export and sync even if no changes*/ |
| 1391 | int bNeedRepack = 0; /* True if we should run repack at the end */ |
| @@ -1331,11 +1402,11 @@ | |
| 1402 | if( zLimit ){ |
| 1403 | nLimit = (unsigned int)atoi(zLimit); |
| 1404 | if( nLimit<=0 ) fossil_fatal("--limit must be positive"); |
| 1405 | } |
| 1406 | zAutoPush = find_option("autopush",0,1); |
| 1407 | zMainBr = (char*)find_option("mainbranch",0,1); |
| 1408 | bForce = find_option("force","f",0)!=0; |
| 1409 | bIfExists = find_option("if-mirrored",0,0)!=0; |
| 1410 | gitmirror_verbosity = VERB_NORMAL; |
| 1411 | while( find_option("quiet","q",0)!=0 ){ gitmirror_verbosity--; } |
| 1412 | while( find_option("verbose","v",0)!=0 ){ gitmirror_verbosity++; } |
| @@ -1350,25 +1421,28 @@ | |
| 1421 | zMirror = db_get("last-git-export-repo", 0); |
| 1422 | if( zMirror==0 ){ |
| 1423 | if( bIfExists ) return; |
| 1424 | fossil_fatal("no Git repository specified"); |
| 1425 | } |
| 1426 | |
| 1427 | if( zMainBr ){ |
| 1428 | z = fossil_strdup(zMainBr); |
| 1429 | gitmirror_sanitize_name(z); |
| 1430 | if( strcmp(z, zMainBr) ){ |
| 1431 | fossil_fatal("\"%s\" is not a legal branch name for Git", zMainBr); |
| 1432 | } |
| 1433 | fossil_free(z); |
| 1434 | } |
| 1435 | |
| 1436 | /* Make sure the GIT repository directory exists */ |
| 1437 | rc = file_mkdir(zMirror, ExtFILE, 0); |
| 1438 | if( rc ) fossil_fatal("cannot create directory \"%s\"", zMirror); |
| 1439 | |
| 1440 | /* Make sure GIT has been initialized */ |
| 1441 | z = mprintf("%s/.git", zMirror); |
| 1442 | if( !file_isdir(z, ExtFILE) ){ |
| 1443 | zMainBr = gitmirror_init(zMirror, zMainBr); |
| 1444 | bNeedRepack = 1; |
| 1445 | } |
| 1446 | fossil_free(z); |
| 1447 | |
| 1448 | /* Make sure the .mirror_state subdirectory exists */ |
| 1449 |