Fossil SCM
Enhance the 'deconstruct' and 'reconstruct' commands with a new command-line option to save and restore the list of private artifacts.
Commit
66a14e93c7b275cd71848aaa8edb2f5674fcc0faf44910a4577b4bdcd64fda17
Parent
836a85cbaead8fe…
1 file changed
+73
+73
| --- src/rebuild.c | ||
| +++ src/rebuild.c | ||
| @@ -1133,10 +1133,60 @@ | ||
| 1133 | 1133 | free(zFNameFormat); |
| 1134 | 1134 | zFNameFormat = 0; |
| 1135 | 1135 | cchFNamePrefix = 0; |
| 1136 | 1136 | } |
| 1137 | 1137 | #endif |
| 1138 | + | |
| 1139 | +/* | |
| 1140 | +** Helper functions used by the `deconstruct' and `reconstruct' commands to | |
| 1141 | +** save and restore the contents of the PRIVATE table. | |
| 1142 | +*/ | |
| 1143 | +void private_export(char *zFileName) | |
| 1144 | +{ | |
| 1145 | + Stmt q; | |
| 1146 | + Blob fctx = empty_blob; | |
| 1147 | + blob_append(&fctx, "# The UUIDs of private artifacts\n", -1); | |
| 1148 | + db_prepare(&q, | |
| 1149 | + "SELECT uuid FROM blob WHERE rid IN ( SELECT rid FROM private );"); | |
| 1150 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 1151 | + const char *zUuid = db_column_text(&q, 0); | |
| 1152 | + blob_append(&fctx, zUuid, -1); | |
| 1153 | + blob_append(&fctx, "\n", -1); | |
| 1154 | + } | |
| 1155 | + db_finalize(&q); | |
| 1156 | + blob_write_to_file(&fctx, zFileName); | |
| 1157 | + blob_reset(&fctx); | |
| 1158 | +} | |
| 1159 | +int private_import(char *zFileName) | |
| 1160 | +{ | |
| 1161 | + if( file_size(zFileName, ExtFILE)>0 ){ | |
| 1162 | + Blob fctx; | |
| 1163 | + if( blob_read_from_file(&fctx, zFileName, ExtFILE)!=-1 ){ | |
| 1164 | + Blob line, value; | |
| 1165 | + while( blob_line(&fctx, &line)>0 ){ | |
| 1166 | + char *zUuid; | |
| 1167 | + int nUuid; | |
| 1168 | + if( blob_token(&line, &value)==0 ) continue; /* Empty line */ | |
| 1169 | + if( blob_buffer(&value)[0]=='#' ) continue; /* Comment */ | |
| 1170 | + blob_trim(&value); | |
| 1171 | + zUuid = blob_buffer(&value); | |
| 1172 | + nUuid = blob_size(&value); | |
| 1173 | + zUuid[nUuid] = 0; | |
| 1174 | + if( hname_validate(zUuid, nUuid)!=HNAME_ERROR ){ | |
| 1175 | + canonical16(zUuid, nUuid); | |
| 1176 | + db_multi_exec( | |
| 1177 | + "INSERT OR IGNORE INTO private" | |
| 1178 | + " SELECT rid FROM blob WHERE uuid = %Q;", | |
| 1179 | + zUuid); | |
| 1180 | + } | |
| 1181 | + } | |
| 1182 | + blob_reset(&fctx); | |
| 1183 | + return 1; | |
| 1184 | + } | |
| 1185 | + } | |
| 1186 | + return 0; | |
| 1187 | +} | |
| 1138 | 1188 | |
| 1139 | 1189 | /* |
| 1140 | 1190 | ** COMMAND: reconstruct* |
| 1141 | 1191 | ** |
| 1142 | 1192 | ** Usage: %fossil reconstruct ?OPTIONS? FILENAME DIRECTORY |
| @@ -1152,11 +1202,13 @@ | ||
| 1152 | 1202 | ** |
| 1153 | 1203 | ** See also: deconstruct, rebuild |
| 1154 | 1204 | */ |
| 1155 | 1205 | void reconstruct_cmd(void) { |
| 1156 | 1206 | char *zPassword; |
| 1207 | + int fKeepPrivate; | |
| 1157 | 1208 | fKeepRid1 = find_option("keep-rid1","K",0)!=0; |
| 1209 | + fKeepPrivate = find_option("keep-private","P",0)!=0; | |
| 1158 | 1210 | if( g.argc!=4 ){ |
| 1159 | 1211 | usage("FILENAME DIRECTORY"); |
| 1160 | 1212 | } |
| 1161 | 1213 | if( file_isdir(g.argv[3], ExtFILE)!=1 ){ |
| 1162 | 1214 | fossil_print("\"%s\" is not a directory\n\n", g.argv[3]); |
| @@ -1175,11 +1227,21 @@ | ||
| 1175 | 1227 | fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]); |
| 1176 | 1228 | recon_read_dir(g.argv[3]); |
| 1177 | 1229 | fossil_print("\nBuilding the Fossil repository...\n"); |
| 1178 | 1230 | |
| 1179 | 1231 | rebuild_db(0, 1, 1); |
| 1232 | + | |
| 1233 | + /* Backwards compatibility: Mark check-ins with "+private" tags as private. */ | |
| 1180 | 1234 | reconstruct_private_table(); |
| 1235 | + /* Newer method: Import the list of private artifacts to the PRIVATE table. */ | |
| 1236 | + if( fKeepPrivate ){ | |
| 1237 | + char *zFnDotPrivate = mprintf("%s/.private", g.argv[3]); | |
| 1238 | + if( private_import(zFnDotPrivate)==0 ){ | |
| 1239 | + fossil_warning("Warning: failure reading the list of private artifacts."); | |
| 1240 | + } | |
| 1241 | + free(zFnDotPrivate); | |
| 1242 | + } | |
| 1181 | 1243 | |
| 1182 | 1244 | /* Skip the verify_before_commit() step on a reconstruct. Most artifacts |
| 1183 | 1245 | ** will have been changed and verification therefore takes a really, really |
| 1184 | 1246 | ** long time. |
| 1185 | 1247 | */ |
| @@ -1217,10 +1279,11 @@ | ||
| 1217 | 1279 | */ |
| 1218 | 1280 | void deconstruct_cmd(void){ |
| 1219 | 1281 | const char *zPrefixOpt; |
| 1220 | 1282 | Stmt s; |
| 1221 | 1283 | int privateFlag; |
| 1284 | + int fKeepPrivate; | |
| 1222 | 1285 | |
| 1223 | 1286 | fKeepRid1 = find_option("keep-rid1","K",0)!=0; |
| 1224 | 1287 | /* get and check prefix length argument and build format string */ |
| 1225 | 1288 | zPrefixOpt=find_option("prefixlength","L",1); |
| 1226 | 1289 | if( !zPrefixOpt ){ |
| @@ -1233,10 +1296,12 @@ | ||
| 1233 | 1296 | } |
| 1234 | 1297 | } |
| 1235 | 1298 | /* open repository and open query for all artifacts */ |
| 1236 | 1299 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); |
| 1237 | 1300 | privateFlag = find_option("private",0,0)!=0; |
| 1301 | + fKeepPrivate = find_option("keep-private","P",0)!=0; | |
| 1302 | + if( fKeepPrivate ) privateFlag = 1; | |
| 1238 | 1303 | verify_all_options(); |
| 1239 | 1304 | /* check number of arguments */ |
| 1240 | 1305 | if( g.argc!=3 ){ |
| 1241 | 1306 | usage ("?OPTIONS? DESTINATION"); |
| 1242 | 1307 | } |
| @@ -1300,13 +1365,21 @@ | ||
| 1300 | 1365 | rebuild_step(rid, size, &content); |
| 1301 | 1366 | } |
| 1302 | 1367 | } |
| 1303 | 1368 | } |
| 1304 | 1369 | db_finalize(&s); |
| 1370 | + | |
| 1371 | + /* Export the list of private artifacts. */ | |
| 1372 | + if( fKeepPrivate ){ | |
| 1373 | + char *zFnDotPrivate = mprintf("%s/.private", zDestDir); | |
| 1374 | + private_export(zFnDotPrivate); | |
| 1375 | + free(zFnDotPrivate); | |
| 1376 | + } | |
| 1377 | + | |
| 1305 | 1378 | if(!g.fQuiet && ttyOutput ){ |
| 1306 | 1379 | fossil_print("\n"); |
| 1307 | 1380 | } |
| 1308 | 1381 | |
| 1309 | 1382 | /* free filename format string */ |
| 1310 | 1383 | free(zFNameFormat); |
| 1311 | 1384 | zFNameFormat = 0; |
| 1312 | 1385 | } |
| 1313 | 1386 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -1133,10 +1133,60 @@ | |
| 1133 | free(zFNameFormat); |
| 1134 | zFNameFormat = 0; |
| 1135 | cchFNamePrefix = 0; |
| 1136 | } |
| 1137 | #endif |
| 1138 | |
| 1139 | /* |
| 1140 | ** COMMAND: reconstruct* |
| 1141 | ** |
| 1142 | ** Usage: %fossil reconstruct ?OPTIONS? FILENAME DIRECTORY |
| @@ -1152,11 +1202,13 @@ | |
| 1152 | ** |
| 1153 | ** See also: deconstruct, rebuild |
| 1154 | */ |
| 1155 | void reconstruct_cmd(void) { |
| 1156 | char *zPassword; |
| 1157 | fKeepRid1 = find_option("keep-rid1","K",0)!=0; |
| 1158 | if( g.argc!=4 ){ |
| 1159 | usage("FILENAME DIRECTORY"); |
| 1160 | } |
| 1161 | if( file_isdir(g.argv[3], ExtFILE)!=1 ){ |
| 1162 | fossil_print("\"%s\" is not a directory\n\n", g.argv[3]); |
| @@ -1175,11 +1227,21 @@ | |
| 1175 | fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]); |
| 1176 | recon_read_dir(g.argv[3]); |
| 1177 | fossil_print("\nBuilding the Fossil repository...\n"); |
| 1178 | |
| 1179 | rebuild_db(0, 1, 1); |
| 1180 | reconstruct_private_table(); |
| 1181 | |
| 1182 | /* Skip the verify_before_commit() step on a reconstruct. Most artifacts |
| 1183 | ** will have been changed and verification therefore takes a really, really |
| 1184 | ** long time. |
| 1185 | */ |
| @@ -1217,10 +1279,11 @@ | |
| 1217 | */ |
| 1218 | void deconstruct_cmd(void){ |
| 1219 | const char *zPrefixOpt; |
| 1220 | Stmt s; |
| 1221 | int privateFlag; |
| 1222 | |
| 1223 | fKeepRid1 = find_option("keep-rid1","K",0)!=0; |
| 1224 | /* get and check prefix length argument and build format string */ |
| 1225 | zPrefixOpt=find_option("prefixlength","L",1); |
| 1226 | if( !zPrefixOpt ){ |
| @@ -1233,10 +1296,12 @@ | |
| 1233 | } |
| 1234 | } |
| 1235 | /* open repository and open query for all artifacts */ |
| 1236 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); |
| 1237 | privateFlag = find_option("private",0,0)!=0; |
| 1238 | verify_all_options(); |
| 1239 | /* check number of arguments */ |
| 1240 | if( g.argc!=3 ){ |
| 1241 | usage ("?OPTIONS? DESTINATION"); |
| 1242 | } |
| @@ -1300,13 +1365,21 @@ | |
| 1300 | rebuild_step(rid, size, &content); |
| 1301 | } |
| 1302 | } |
| 1303 | } |
| 1304 | db_finalize(&s); |
| 1305 | if(!g.fQuiet && ttyOutput ){ |
| 1306 | fossil_print("\n"); |
| 1307 | } |
| 1308 | |
| 1309 | /* free filename format string */ |
| 1310 | free(zFNameFormat); |
| 1311 | zFNameFormat = 0; |
| 1312 | } |
| 1313 |
| --- src/rebuild.c | |
| +++ src/rebuild.c | |
| @@ -1133,10 +1133,60 @@ | |
| 1133 | free(zFNameFormat); |
| 1134 | zFNameFormat = 0; |
| 1135 | cchFNamePrefix = 0; |
| 1136 | } |
| 1137 | #endif |
| 1138 | |
| 1139 | /* |
| 1140 | ** Helper functions used by the `deconstruct' and `reconstruct' commands to |
| 1141 | ** save and restore the contents of the PRIVATE table. |
| 1142 | */ |
| 1143 | void private_export(char *zFileName) |
| 1144 | { |
| 1145 | Stmt q; |
| 1146 | Blob fctx = empty_blob; |
| 1147 | blob_append(&fctx, "# The UUIDs of private artifacts\n", -1); |
| 1148 | db_prepare(&q, |
| 1149 | "SELECT uuid FROM blob WHERE rid IN ( SELECT rid FROM private );"); |
| 1150 | while( db_step(&q)==SQLITE_ROW ){ |
| 1151 | const char *zUuid = db_column_text(&q, 0); |
| 1152 | blob_append(&fctx, zUuid, -1); |
| 1153 | blob_append(&fctx, "\n", -1); |
| 1154 | } |
| 1155 | db_finalize(&q); |
| 1156 | blob_write_to_file(&fctx, zFileName); |
| 1157 | blob_reset(&fctx); |
| 1158 | } |
| 1159 | int private_import(char *zFileName) |
| 1160 | { |
| 1161 | if( file_size(zFileName, ExtFILE)>0 ){ |
| 1162 | Blob fctx; |
| 1163 | if( blob_read_from_file(&fctx, zFileName, ExtFILE)!=-1 ){ |
| 1164 | Blob line, value; |
| 1165 | while( blob_line(&fctx, &line)>0 ){ |
| 1166 | char *zUuid; |
| 1167 | int nUuid; |
| 1168 | if( blob_token(&line, &value)==0 ) continue; /* Empty line */ |
| 1169 | if( blob_buffer(&value)[0]=='#' ) continue; /* Comment */ |
| 1170 | blob_trim(&value); |
| 1171 | zUuid = blob_buffer(&value); |
| 1172 | nUuid = blob_size(&value); |
| 1173 | zUuid[nUuid] = 0; |
| 1174 | if( hname_validate(zUuid, nUuid)!=HNAME_ERROR ){ |
| 1175 | canonical16(zUuid, nUuid); |
| 1176 | db_multi_exec( |
| 1177 | "INSERT OR IGNORE INTO private" |
| 1178 | " SELECT rid FROM blob WHERE uuid = %Q;", |
| 1179 | zUuid); |
| 1180 | } |
| 1181 | } |
| 1182 | blob_reset(&fctx); |
| 1183 | return 1; |
| 1184 | } |
| 1185 | } |
| 1186 | return 0; |
| 1187 | } |
| 1188 | |
| 1189 | /* |
| 1190 | ** COMMAND: reconstruct* |
| 1191 | ** |
| 1192 | ** Usage: %fossil reconstruct ?OPTIONS? FILENAME DIRECTORY |
| @@ -1152,11 +1202,13 @@ | |
| 1202 | ** |
| 1203 | ** See also: deconstruct, rebuild |
| 1204 | */ |
| 1205 | void reconstruct_cmd(void) { |
| 1206 | char *zPassword; |
| 1207 | int fKeepPrivate; |
| 1208 | fKeepRid1 = find_option("keep-rid1","K",0)!=0; |
| 1209 | fKeepPrivate = find_option("keep-private","P",0)!=0; |
| 1210 | if( g.argc!=4 ){ |
| 1211 | usage("FILENAME DIRECTORY"); |
| 1212 | } |
| 1213 | if( file_isdir(g.argv[3], ExtFILE)!=1 ){ |
| 1214 | fossil_print("\"%s\" is not a directory\n\n", g.argv[3]); |
| @@ -1175,11 +1227,21 @@ | |
| 1227 | fossil_print("Reading files from directory \"%s\"...\n", g.argv[3]); |
| 1228 | recon_read_dir(g.argv[3]); |
| 1229 | fossil_print("\nBuilding the Fossil repository...\n"); |
| 1230 | |
| 1231 | rebuild_db(0, 1, 1); |
| 1232 | |
| 1233 | /* Backwards compatibility: Mark check-ins with "+private" tags as private. */ |
| 1234 | reconstruct_private_table(); |
| 1235 | /* Newer method: Import the list of private artifacts to the PRIVATE table. */ |
| 1236 | if( fKeepPrivate ){ |
| 1237 | char *zFnDotPrivate = mprintf("%s/.private", g.argv[3]); |
| 1238 | if( private_import(zFnDotPrivate)==0 ){ |
| 1239 | fossil_warning("Warning: failure reading the list of private artifacts."); |
| 1240 | } |
| 1241 | free(zFnDotPrivate); |
| 1242 | } |
| 1243 | |
| 1244 | /* Skip the verify_before_commit() step on a reconstruct. Most artifacts |
| 1245 | ** will have been changed and verification therefore takes a really, really |
| 1246 | ** long time. |
| 1247 | */ |
| @@ -1217,10 +1279,11 @@ | |
| 1279 | */ |
| 1280 | void deconstruct_cmd(void){ |
| 1281 | const char *zPrefixOpt; |
| 1282 | Stmt s; |
| 1283 | int privateFlag; |
| 1284 | int fKeepPrivate; |
| 1285 | |
| 1286 | fKeepRid1 = find_option("keep-rid1","K",0)!=0; |
| 1287 | /* get and check prefix length argument and build format string */ |
| 1288 | zPrefixOpt=find_option("prefixlength","L",1); |
| 1289 | if( !zPrefixOpt ){ |
| @@ -1233,10 +1296,12 @@ | |
| 1296 | } |
| 1297 | } |
| 1298 | /* open repository and open query for all artifacts */ |
| 1299 | db_find_and_open_repository(OPEN_ANY_SCHEMA, 0); |
| 1300 | privateFlag = find_option("private",0,0)!=0; |
| 1301 | fKeepPrivate = find_option("keep-private","P",0)!=0; |
| 1302 | if( fKeepPrivate ) privateFlag = 1; |
| 1303 | verify_all_options(); |
| 1304 | /* check number of arguments */ |
| 1305 | if( g.argc!=3 ){ |
| 1306 | usage ("?OPTIONS? DESTINATION"); |
| 1307 | } |
| @@ -1300,13 +1365,21 @@ | |
| 1365 | rebuild_step(rid, size, &content); |
| 1366 | } |
| 1367 | } |
| 1368 | } |
| 1369 | db_finalize(&s); |
| 1370 | |
| 1371 | /* Export the list of private artifacts. */ |
| 1372 | if( fKeepPrivate ){ |
| 1373 | char *zFnDotPrivate = mprintf("%s/.private", zDestDir); |
| 1374 | private_export(zFnDotPrivate); |
| 1375 | free(zFnDotPrivate); |
| 1376 | } |
| 1377 | |
| 1378 | if(!g.fQuiet && ttyOutput ){ |
| 1379 | fossil_print("\n"); |
| 1380 | } |
| 1381 | |
| 1382 | /* free filename format string */ |
| 1383 | free(zFNameFormat); |
| 1384 | zFNameFormat = 0; |
| 1385 | } |
| 1386 |