Fossil SCM
Do the export within a transaction for performance. Record a complete two-way map of Git and Fossil names in the mirror.mmark table.
Commit
c4f9b177f4dfa1891ac1aaa817abae821928e3c1e90a997955ca579aac9576d4
Parent
051cd3825ed507b…
1 file changed
+29
-33
+29
-33
| --- src/export.c | ||
| +++ src/export.c | ||
| @@ -912,22 +912,10 @@ | ||
| 912 | 912 | zOut[j++] = '"'; |
| 913 | 913 | zOut[j] = 0; |
| 914 | 914 | return zOut; |
| 915 | 915 | } |
| 916 | 916 | |
| 917 | -/* | |
| 918 | -** Transfer a tag over to the mirror. "rid" is the BLOB.RID value for | |
| 919 | -** the record that describes the tag. | |
| 920 | -** | |
| 921 | -** The Git tag mechanism is very limited compared to Fossil. Many Fossil | |
| 922 | -** tags cannot be exported to Git. If this tag cannot be exported, then | |
| 923 | -** silently ignore it. | |
| 924 | -*/ | |
| 925 | -static void gitmirror_send_tag(FILE *xCmd, int rid){ | |
| 926 | - return; | |
| 927 | -} | |
| 928 | - | |
| 929 | 917 | /* |
| 930 | 918 | ** Locate the mark for a UUID. |
| 931 | 919 | ** |
| 932 | 920 | ** If the mark does not exist and if the bCreate flag is false, then |
| 933 | 921 | ** return 0. If the mark does not exist and the bCreate flag is true, |
| @@ -1210,28 +1198,26 @@ | ||
| 1210 | 1198 | if( rc ) fossil_fatal("cannot create directory \"%s\"", z); |
| 1211 | 1199 | fossil_free(z); |
| 1212 | 1200 | |
| 1213 | 1201 | /* Attach the .mirror_state/db database */ |
| 1214 | 1202 | db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror); |
| 1203 | + db_begin_write(); | |
| 1215 | 1204 | db_multi_exec( |
| 1216 | 1205 | "CREATE TABLE IF NOT EXISTS mirror.mconfig(\n" |
| 1217 | 1206 | " key TEXT PRIMARY KEY,\n" |
| 1218 | 1207 | " Value ANY\n" |
| 1219 | 1208 | ") WITHOUT ROWID;\n" |
| 1220 | 1209 | "CREATE TABLE IF NOT EXISTS mirror.mmark(\n" |
| 1221 | 1210 | " id INTEGER PRIMARY KEY,\n" |
| 1222 | - " uuid TEXT UNIQUE\n" | |
| 1211 | + " uuid TEXT UNIQUE,\n" | |
| 1212 | + " githash TEXT UNIQUE\n" | |
| 1223 | 1213 | ");" |
| 1224 | - "CREATE TABLE IF NOT EXISTS mirror.mtag(\n" | |
| 1225 | - " tagname TEXT PRIMARY KEY,\n" | |
| 1226 | - " cnt INTEGER DEFAULT 1\n" | |
| 1227 | - ") WITHOUT ROWID;" | |
| 1228 | 1214 | ); |
| 1229 | 1215 | |
| 1230 | 1216 | /* See if there is any work to be done. Exit early if not, before starting |
| 1231 | 1217 | ** the "git fast-import" command. */ |
| 1232 | - if( !db_exists("SELECT 1 FROM event WHERE type IN ('t','ci')" | |
| 1218 | + if( !db_exists("SELECT 1 FROM event WHERE type='ci'" | |
| 1233 | 1219 | " AND mtime>coalesce((SELECT value FROM mconfig" |
| 1234 | 1220 | " WHERE key='start'),0.0)") |
| 1235 | 1221 | ){ |
| 1236 | 1222 | fossil_print("no changes\n"); |
| 1237 | 1223 | return; |
| @@ -1267,40 +1253,35 @@ | ||
| 1267 | 1253 | } |
| 1268 | 1254 | |
| 1269 | 1255 | /* Run the export */ |
| 1270 | 1256 | rEnd = 0.0; |
| 1271 | 1257 | db_multi_exec( |
| 1272 | - "CREATE TEMP TABLE tomirror(objid INTEGER PRIMARY KEY,type,mtime,uuid);\n" | |
| 1258 | + "CREATE TEMP TABLE tomirror(objid,mtime,uuid);\n" | |
| 1273 | 1259 | "INSERT INTO tomirror " |
| 1274 | - "SELECT objid, type, mtime, blob.uuid FROM event, blob\n" | |
| 1275 | - " WHERE type IN ('ci','t')" | |
| 1260 | + "SELECT objid, mtime, blob.uuid FROM event, blob\n" | |
| 1261 | + " WHERE type='ci'" | |
| 1276 | 1262 | " AND mtime>coalesce((SELECT value FROM mconfig WHERE key='start'),0.0)" |
| 1277 | 1263 | " AND blob.rid=event.objid" |
| 1278 | 1264 | " AND blob.uuid NOT IN (SELECT uuid FROM mirror.mmark);" |
| 1279 | 1265 | ); |
| 1280 | - nTotal = db_int(0, "SELECT count(*) FROM tomirror WHERE type='ci'"); | |
| 1266 | + nTotal = db_int(0, "SELECT count(*) FROM tomirror"); | |
| 1281 | 1267 | if( nLimit<nTotal ){ |
| 1282 | 1268 | nTotal = nLimit; |
| 1283 | 1269 | }else if( nLimit>nTotal ){ |
| 1284 | 1270 | nLimit = nTotal; |
| 1285 | 1271 | } |
| 1286 | 1272 | db_prepare(&q, |
| 1287 | - "SELECT objid, type, mtime, uuid FROM tomirror ORDER BY mtime" | |
| 1273 | + "SELECT objid, mtime, uuid FROM tomirror ORDER BY mtime" | |
| 1288 | 1274 | ); |
| 1289 | 1275 | while( nLimit && db_step(&q)==SQLITE_ROW ){ |
| 1290 | - double rMTime = db_column_double(&q, 2); | |
| 1291 | - const char *zType = db_column_text(&q, 1); | |
| 1292 | 1276 | int rid = db_column_int(&q, 0); |
| 1293 | - const char *zUuid = db_column_text(&q, 3); | |
| 1277 | + double rMTime = db_column_double(&q, 1); | |
| 1278 | + const char *zUuid = db_column_text(&q, 2); | |
| 1294 | 1279 | if( rMTime>rEnd ) rEnd = rMTime; |
| 1295 | - if( zType[0]=='t' ){ | |
| 1296 | - gitmirror_send_tag(xCmd, rid); | |
| 1297 | - }else{ | |
| 1298 | - gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest); | |
| 1299 | - printf("\r%d/%d ", nTotal-nLimit, nTotal); | |
| 1300 | - fflush(stdout); | |
| 1301 | - } | |
| 1280 | + gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest); | |
| 1281 | + printf("\r%d/%d ", nTotal-nLimit, nTotal); | |
| 1282 | + fflush(stdout); | |
| 1302 | 1283 | } |
| 1303 | 1284 | db_finalize(&q); |
| 1304 | 1285 | db_prepare(&q, "REPLACE INTO mirror.mconfig(key,value) VALUES('start',:x)"); |
| 1305 | 1286 | db_bind_double(&q, ":x", rEnd); |
| 1306 | 1287 | db_step(&q); |
| @@ -1320,19 +1301,34 @@ | ||
| 1320 | 1301 | if( pOut ){ |
| 1321 | 1302 | pIn = fopen(".mirror_state/in", "ab"); |
| 1322 | 1303 | if( pIn==0 ){ |
| 1323 | 1304 | fossil_fatal("cannot open %s/.mirror_state/in for appending", zMirror); |
| 1324 | 1305 | } |
| 1306 | + db_prepare(&q, "UPDATE mirror.mmark SET githash=:githash WHERE id=:id"); | |
| 1325 | 1307 | while( fgets(zLine, sizeof(zLine), pOut) ){ |
| 1308 | + int j, k; | |
| 1309 | + if( zLine[0]!=':' ) continue; | |
| 1310 | + db_bind_int(&q, ":id", atoi(zLine+1)); | |
| 1311 | + for(j=1; zLine[j] && zLine[j]!=' '; j++){} | |
| 1312 | + if( zLine[j]!=' ' ) continue; | |
| 1313 | + j++; | |
| 1314 | + if( zLine[j]==0 ) continue; | |
| 1315 | + for(k=j; fossil_isalnum(zLine[k]); k++){} | |
| 1316 | + zLine[k] = 0; | |
| 1317 | + db_bind_text(&q, ":githash", &zLine[j]); | |
| 1318 | + db_step(&q); | |
| 1319 | + db_reset(&q); | |
| 1326 | 1320 | fputs(zLine, pIn); |
| 1327 | 1321 | } |
| 1322 | + db_finalize(&q); | |
| 1328 | 1323 | fclose(pOut); |
| 1329 | 1324 | fclose(pIn); |
| 1330 | 1325 | file_delete(".mirror_state/out"); |
| 1331 | 1326 | }else{ |
| 1332 | 1327 | fossil_fatal("git fast-import didn't generate a marks file!"); |
| 1333 | 1328 | } |
| 1329 | + db_commit_transaction(); | |
| 1334 | 1330 | |
| 1335 | 1331 | /* Optionally do a "git push" */ |
| 1336 | 1332 | } |
| 1337 | 1333 | |
| 1338 | 1334 | /* |
| 1339 | 1335 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -912,22 +912,10 @@ | |
| 912 | zOut[j++] = '"'; |
| 913 | zOut[j] = 0; |
| 914 | return zOut; |
| 915 | } |
| 916 | |
| 917 | /* |
| 918 | ** Transfer a tag over to the mirror. "rid" is the BLOB.RID value for |
| 919 | ** the record that describes the tag. |
| 920 | ** |
| 921 | ** The Git tag mechanism is very limited compared to Fossil. Many Fossil |
| 922 | ** tags cannot be exported to Git. If this tag cannot be exported, then |
| 923 | ** silently ignore it. |
| 924 | */ |
| 925 | static void gitmirror_send_tag(FILE *xCmd, int rid){ |
| 926 | return; |
| 927 | } |
| 928 | |
| 929 | /* |
| 930 | ** Locate the mark for a UUID. |
| 931 | ** |
| 932 | ** If the mark does not exist and if the bCreate flag is false, then |
| 933 | ** return 0. If the mark does not exist and the bCreate flag is true, |
| @@ -1210,28 +1198,26 @@ | |
| 1210 | if( rc ) fossil_fatal("cannot create directory \"%s\"", z); |
| 1211 | fossil_free(z); |
| 1212 | |
| 1213 | /* Attach the .mirror_state/db database */ |
| 1214 | db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror); |
| 1215 | db_multi_exec( |
| 1216 | "CREATE TABLE IF NOT EXISTS mirror.mconfig(\n" |
| 1217 | " key TEXT PRIMARY KEY,\n" |
| 1218 | " Value ANY\n" |
| 1219 | ") WITHOUT ROWID;\n" |
| 1220 | "CREATE TABLE IF NOT EXISTS mirror.mmark(\n" |
| 1221 | " id INTEGER PRIMARY KEY,\n" |
| 1222 | " uuid TEXT UNIQUE\n" |
| 1223 | ");" |
| 1224 | "CREATE TABLE IF NOT EXISTS mirror.mtag(\n" |
| 1225 | " tagname TEXT PRIMARY KEY,\n" |
| 1226 | " cnt INTEGER DEFAULT 1\n" |
| 1227 | ") WITHOUT ROWID;" |
| 1228 | ); |
| 1229 | |
| 1230 | /* See if there is any work to be done. Exit early if not, before starting |
| 1231 | ** the "git fast-import" command. */ |
| 1232 | if( !db_exists("SELECT 1 FROM event WHERE type IN ('t','ci')" |
| 1233 | " AND mtime>coalesce((SELECT value FROM mconfig" |
| 1234 | " WHERE key='start'),0.0)") |
| 1235 | ){ |
| 1236 | fossil_print("no changes\n"); |
| 1237 | return; |
| @@ -1267,40 +1253,35 @@ | |
| 1267 | } |
| 1268 | |
| 1269 | /* Run the export */ |
| 1270 | rEnd = 0.0; |
| 1271 | db_multi_exec( |
| 1272 | "CREATE TEMP TABLE tomirror(objid INTEGER PRIMARY KEY,type,mtime,uuid);\n" |
| 1273 | "INSERT INTO tomirror " |
| 1274 | "SELECT objid, type, mtime, blob.uuid FROM event, blob\n" |
| 1275 | " WHERE type IN ('ci','t')" |
| 1276 | " AND mtime>coalesce((SELECT value FROM mconfig WHERE key='start'),0.0)" |
| 1277 | " AND blob.rid=event.objid" |
| 1278 | " AND blob.uuid NOT IN (SELECT uuid FROM mirror.mmark);" |
| 1279 | ); |
| 1280 | nTotal = db_int(0, "SELECT count(*) FROM tomirror WHERE type='ci'"); |
| 1281 | if( nLimit<nTotal ){ |
| 1282 | nTotal = nLimit; |
| 1283 | }else if( nLimit>nTotal ){ |
| 1284 | nLimit = nTotal; |
| 1285 | } |
| 1286 | db_prepare(&q, |
| 1287 | "SELECT objid, type, mtime, uuid FROM tomirror ORDER BY mtime" |
| 1288 | ); |
| 1289 | while( nLimit && db_step(&q)==SQLITE_ROW ){ |
| 1290 | double rMTime = db_column_double(&q, 2); |
| 1291 | const char *zType = db_column_text(&q, 1); |
| 1292 | int rid = db_column_int(&q, 0); |
| 1293 | const char *zUuid = db_column_text(&q, 3); |
| 1294 | if( rMTime>rEnd ) rEnd = rMTime; |
| 1295 | if( zType[0]=='t' ){ |
| 1296 | gitmirror_send_tag(xCmd, rid); |
| 1297 | }else{ |
| 1298 | gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest); |
| 1299 | printf("\r%d/%d ", nTotal-nLimit, nTotal); |
| 1300 | fflush(stdout); |
| 1301 | } |
| 1302 | } |
| 1303 | db_finalize(&q); |
| 1304 | db_prepare(&q, "REPLACE INTO mirror.mconfig(key,value) VALUES('start',:x)"); |
| 1305 | db_bind_double(&q, ":x", rEnd); |
| 1306 | db_step(&q); |
| @@ -1320,19 +1301,34 @@ | |
| 1320 | if( pOut ){ |
| 1321 | pIn = fopen(".mirror_state/in", "ab"); |
| 1322 | if( pIn==0 ){ |
| 1323 | fossil_fatal("cannot open %s/.mirror_state/in for appending", zMirror); |
| 1324 | } |
| 1325 | while( fgets(zLine, sizeof(zLine), pOut) ){ |
| 1326 | fputs(zLine, pIn); |
| 1327 | } |
| 1328 | fclose(pOut); |
| 1329 | fclose(pIn); |
| 1330 | file_delete(".mirror_state/out"); |
| 1331 | }else{ |
| 1332 | fossil_fatal("git fast-import didn't generate a marks file!"); |
| 1333 | } |
| 1334 | |
| 1335 | /* Optionally do a "git push" */ |
| 1336 | } |
| 1337 | |
| 1338 | /* |
| 1339 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -912,22 +912,10 @@ | |
| 912 | zOut[j++] = '"'; |
| 913 | zOut[j] = 0; |
| 914 | return zOut; |
| 915 | } |
| 916 | |
| 917 | /* |
| 918 | ** Locate the mark for a UUID. |
| 919 | ** |
| 920 | ** If the mark does not exist and if the bCreate flag is false, then |
| 921 | ** return 0. If the mark does not exist and the bCreate flag is true, |
| @@ -1210,28 +1198,26 @@ | |
| 1198 | if( rc ) fossil_fatal("cannot create directory \"%s\"", z); |
| 1199 | fossil_free(z); |
| 1200 | |
| 1201 | /* Attach the .mirror_state/db database */ |
| 1202 | db_multi_exec("ATTACH '%q/.mirror_state/db' AS mirror;", zMirror); |
| 1203 | db_begin_write(); |
| 1204 | db_multi_exec( |
| 1205 | "CREATE TABLE IF NOT EXISTS mirror.mconfig(\n" |
| 1206 | " key TEXT PRIMARY KEY,\n" |
| 1207 | " Value ANY\n" |
| 1208 | ") WITHOUT ROWID;\n" |
| 1209 | "CREATE TABLE IF NOT EXISTS mirror.mmark(\n" |
| 1210 | " id INTEGER PRIMARY KEY,\n" |
| 1211 | " uuid TEXT UNIQUE,\n" |
| 1212 | " githash TEXT UNIQUE\n" |
| 1213 | ");" |
| 1214 | ); |
| 1215 | |
| 1216 | /* See if there is any work to be done. Exit early if not, before starting |
| 1217 | ** the "git fast-import" command. */ |
| 1218 | if( !db_exists("SELECT 1 FROM event WHERE type='ci'" |
| 1219 | " AND mtime>coalesce((SELECT value FROM mconfig" |
| 1220 | " WHERE key='start'),0.0)") |
| 1221 | ){ |
| 1222 | fossil_print("no changes\n"); |
| 1223 | return; |
| @@ -1267,40 +1253,35 @@ | |
| 1253 | } |
| 1254 | |
| 1255 | /* Run the export */ |
| 1256 | rEnd = 0.0; |
| 1257 | db_multi_exec( |
| 1258 | "CREATE TEMP TABLE tomirror(objid,mtime,uuid);\n" |
| 1259 | "INSERT INTO tomirror " |
| 1260 | "SELECT objid, mtime, blob.uuid FROM event, blob\n" |
| 1261 | " WHERE type='ci'" |
| 1262 | " AND mtime>coalesce((SELECT value FROM mconfig WHERE key='start'),0.0)" |
| 1263 | " AND blob.rid=event.objid" |
| 1264 | " AND blob.uuid NOT IN (SELECT uuid FROM mirror.mmark);" |
| 1265 | ); |
| 1266 | nTotal = db_int(0, "SELECT count(*) FROM tomirror"); |
| 1267 | if( nLimit<nTotal ){ |
| 1268 | nTotal = nLimit; |
| 1269 | }else if( nLimit>nTotal ){ |
| 1270 | nLimit = nTotal; |
| 1271 | } |
| 1272 | db_prepare(&q, |
| 1273 | "SELECT objid, mtime, uuid FROM tomirror ORDER BY mtime" |
| 1274 | ); |
| 1275 | while( nLimit && db_step(&q)==SQLITE_ROW ){ |
| 1276 | int rid = db_column_int(&q, 0); |
| 1277 | double rMTime = db_column_double(&q, 1); |
| 1278 | const char *zUuid = db_column_text(&q, 2); |
| 1279 | if( rMTime>rEnd ) rEnd = rMTime; |
| 1280 | gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest); |
| 1281 | printf("\r%d/%d ", nTotal-nLimit, nTotal); |
| 1282 | fflush(stdout); |
| 1283 | } |
| 1284 | db_finalize(&q); |
| 1285 | db_prepare(&q, "REPLACE INTO mirror.mconfig(key,value) VALUES('start',:x)"); |
| 1286 | db_bind_double(&q, ":x", rEnd); |
| 1287 | db_step(&q); |
| @@ -1320,19 +1301,34 @@ | |
| 1301 | if( pOut ){ |
| 1302 | pIn = fopen(".mirror_state/in", "ab"); |
| 1303 | if( pIn==0 ){ |
| 1304 | fossil_fatal("cannot open %s/.mirror_state/in for appending", zMirror); |
| 1305 | } |
| 1306 | db_prepare(&q, "UPDATE mirror.mmark SET githash=:githash WHERE id=:id"); |
| 1307 | while( fgets(zLine, sizeof(zLine), pOut) ){ |
| 1308 | int j, k; |
| 1309 | if( zLine[0]!=':' ) continue; |
| 1310 | db_bind_int(&q, ":id", atoi(zLine+1)); |
| 1311 | for(j=1; zLine[j] && zLine[j]!=' '; j++){} |
| 1312 | if( zLine[j]!=' ' ) continue; |
| 1313 | j++; |
| 1314 | if( zLine[j]==0 ) continue; |
| 1315 | for(k=j; fossil_isalnum(zLine[k]); k++){} |
| 1316 | zLine[k] = 0; |
| 1317 | db_bind_text(&q, ":githash", &zLine[j]); |
| 1318 | db_step(&q); |
| 1319 | db_reset(&q); |
| 1320 | fputs(zLine, pIn); |
| 1321 | } |
| 1322 | db_finalize(&q); |
| 1323 | fclose(pOut); |
| 1324 | fclose(pIn); |
| 1325 | file_delete(".mirror_state/out"); |
| 1326 | }else{ |
| 1327 | fossil_fatal("git fast-import didn't generate a marks file!"); |
| 1328 | } |
| 1329 | db_commit_transaction(); |
| 1330 | |
| 1331 | /* Optionally do a "git push" */ |
| 1332 | } |
| 1333 | |
| 1334 | /* |
| 1335 |