Fossil SCM
Add support for incremental exports
Commit
c2ccd825223022bcd21dcc3aa037e1e46281ec10
Parent
22d414e517b5846…
1 file changed
+98
-20
+98
-20
| --- src/export.c | ||
| +++ src/export.c | ||
| @@ -84,11 +84,11 @@ | ||
| 84 | 84 | #define COMMITMARK(rid) ((rid) * 2 + 1) |
| 85 | 85 | |
| 86 | 86 | /* |
| 87 | 87 | ** COMMAND: export |
| 88 | 88 | ** |
| 89 | -** Usage: %fossil export --git ?REPOSITORY? | |
| 89 | +** Usage: %fossil export --git ?options? ?REPOSITORY? | |
| 90 | 90 | ** |
| 91 | 91 | ** Write an export of all check-ins to standard output. The export is |
| 92 | 92 | ** written in the git-fast-export file format assuming the --git option is |
| 93 | 93 | ** provided. The git-fast-export format is currently the only VCS |
| 94 | 94 | ** interchange format supported, though other formats may be added in |
| @@ -97,61 +97,117 @@ | ||
| 97 | 97 | ** Run this command within a checkout. Or use the -R or --repository |
| 98 | 98 | ** option to specify a Fossil repository to be exported. |
| 99 | 99 | ** |
| 100 | 100 | ** Only check-ins are exported using --git. Git does not support tickets |
| 101 | 101 | ** or wiki or events or attachments, so none of those are exported. |
| 102 | +** | |
| 103 | +** If the "--import-marks FILE" option is used, it contains a list of | |
| 104 | +** rids to skip. | |
| 105 | +** | |
| 106 | +** If the "--export-marks FILE" option is used, the rid of all commits and | |
| 107 | +** blobs written on exit for use with "--import-marks" on the next run. | |
| 102 | 108 | */ |
| 103 | 109 | void export_cmd(void){ |
| 104 | - Stmt q; | |
| 110 | + Stmt q, q2; | |
| 105 | 111 | int i; |
| 106 | 112 | Bag blobs, vers; |
| 113 | + const char *markfile_in; | |
| 114 | + const char *markfile_out; | |
| 115 | + | |
| 107 | 116 | bag_init(&blobs); |
| 108 | 117 | bag_init(&vers); |
| 109 | 118 | |
| 110 | 119 | find_option("git", 0, 0); /* Ignore the --git option for now */ |
| 120 | + markfile_in = find_option("import-marks", 0, 1); | |
| 121 | + markfile_out = find_option("export-marks", 0, 1); | |
| 122 | + | |
| 111 | 123 | db_find_and_open_repository(0, 2); |
| 112 | 124 | verify_all_options(); |
| 113 | 125 | if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); } |
| 126 | + | |
| 127 | + db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER)"); | |
| 128 | + db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER)"); | |
| 129 | + if( markfile_in!=0 ){ | |
| 130 | + Stmt qb,qc; | |
| 131 | + char line[100]; | |
| 132 | + FILE *f; | |
| 133 | + | |
| 134 | + f = fopen(markfile_in, "r"); | |
| 135 | + if( f==0 ){ | |
| 136 | + fossil_panic("cannot open %s for reading", markfile_in); | |
| 137 | + } | |
| 138 | + db_prepare(&qb, "INSERT INTO oldblob VALUES (:rid)"); | |
| 139 | + db_prepare(&qc, "INSERT INTO oldcommit VALUES (:rid)"); | |
| 140 | + while( fgets(line, sizeof(line), f)!=0 ){ | |
| 141 | + if( *line == 'b' ){ | |
| 142 | + db_bind_text(&qb, ":rid", line + 1); | |
| 143 | + db_step(&qb); | |
| 144 | + db_reset(&qb); | |
| 145 | + bag_insert(&blobs, atoi(line + 1)); | |
| 146 | + }else if( *line == 'c' ){ | |
| 147 | + db_bind_text(&qc, ":rid", line + 1); | |
| 148 | + db_step(&qc); | |
| 149 | + db_reset(&qc); | |
| 150 | + bag_insert(&vers, atoi(line + 1)); | |
| 151 | + }else{ | |
| 152 | + fossil_panic("bad input from %s: %s", markfile_in, line); | |
| 153 | + } | |
| 154 | + } | |
| 155 | + db_finalize(&qb); | |
| 156 | + db_finalize(&qc); | |
| 157 | + fclose(f); | |
| 158 | + } | |
| 114 | 159 | |
| 115 | 160 | /* Step 1: Generate "blob" records for every artifact that is part |
| 116 | 161 | ** of a check-in |
| 117 | 162 | */ |
| 118 | 163 | fossil_binary_mode(stdout); |
| 119 | - db_prepare(&q, "SELECT DISTINCT fid FROM mlink WHERE fid>0"); | |
| 164 | + db_prepare(&q, | |
| 165 | + "SELECT DISTINCT fid FROM mlink" | |
| 166 | + " WHERE fid>0 AND NOT EXISTS(SELECT 1 FROM oldblob WHERE rid=fid)"); | |
| 167 | + db_prepare(&q2, "INSERT INTO oldblob VALUES (:rid)"); | |
| 120 | 168 | while( db_step(&q)==SQLITE_ROW ){ |
| 121 | 169 | int rid = db_column_int(&q, 0); |
| 122 | 170 | Blob content; |
| 123 | 171 | content_get(rid, &content); |
| 172 | + db_bind_int(&q2, ":rid", rid); | |
| 173 | + db_step(&q2); | |
| 174 | + db_reset(&q2); | |
| 124 | 175 | printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content)); |
| 125 | 176 | bag_insert(&blobs, rid); |
| 126 | 177 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 127 | 178 | printf("\n"); |
| 128 | 179 | blob_reset(&content); |
| 129 | 180 | } |
| 130 | 181 | db_finalize(&q); |
| 182 | + db_finalize(&q2); | |
| 131 | 183 | |
| 132 | 184 | /* Output the commit records. |
| 133 | 185 | */ |
| 134 | 186 | db_prepare(&q, |
| 135 | 187 | "SELECT strftime('%%s',mtime), objid, coalesce(comment,ecomment)," |
| 136 | 188 | " coalesce(user,euser)," |
| 137 | 189 | " (SELECT value FROM tagxref WHERE rid=objid AND tagid=%d)" |
| 138 | 190 | " FROM event" |
| 139 | - " WHERE type='ci'" | |
| 191 | + " WHERE type='ci' AND NOT EXISTS (SELECT 1 FROM oldcommit WHERE objid=rid)" | |
| 140 | 192 | " ORDER BY mtime ASC", |
| 141 | 193 | TAG_BRANCH |
| 142 | 194 | ); |
| 195 | + db_prepare(&q2, "INSERT INTO oldcommit VALUES (:rid)"); | |
| 143 | 196 | while( db_step(&q)==SQLITE_ROW ){ |
| 144 | - Stmt q2; | |
| 197 | + Stmt q3; | |
| 145 | 198 | const char *zSecondsSince1970 = db_column_text(&q, 0); |
| 146 | 199 | int ckinId = db_column_int(&q, 1); |
| 147 | 200 | const char *zComment = db_column_text(&q, 2); |
| 148 | 201 | const char *zUser = db_column_text(&q, 3); |
| 149 | 202 | const char *zBranch = db_column_text(&q, 4); |
| 150 | 203 | char *zBr; |
| 151 | 204 | |
| 152 | 205 | bag_insert(&vers, ckinId); |
| 206 | + db_bind_int(&q2, ":rid", ckinId); | |
| 207 | + db_step(&q2); | |
| 208 | + db_reset(&q2); | |
| 153 | 209 | if( zBranch==0 ) zBranch = "trunk"; |
| 154 | 210 | zBr = mprintf("%s", zBranch); |
| 155 | 211 | for(i=0; zBr[i]; i++){ |
| 156 | 212 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 157 | 213 | } |
| @@ -160,12 +216,12 @@ | ||
| 160 | 216 | printf("committer"); |
| 161 | 217 | print_person(zUser); |
| 162 | 218 | printf(" %s +0000\n", zSecondsSince1970); |
| 163 | 219 | if( zComment==0 ) zComment = "null comment"; |
| 164 | 220 | printf("data %d\n%s\n", (int)strlen(zComment), zComment); |
| 165 | - db_prepare(&q2, "SELECT pid FROM plink WHERE cid=%d AND isprim", ckinId); | |
| 166 | - if( db_step(&q2) != SQLITE_ROW ){ | |
| 221 | + db_prepare(&q3, "SELECT pid FROM plink WHERE cid=%d AND isprim", ckinId); | |
| 222 | + if( db_step(&q3) != SQLITE_ROW ){ | |
| 167 | 223 | const char *zFromType; |
| 168 | 224 | Manifest *p; |
| 169 | 225 | ManifestFile *pFile; |
| 170 | 226 | |
| 171 | 227 | zFromType = "from"; |
| @@ -186,46 +242,47 @@ | ||
| 186 | 242 | if( !bag_find(&blobs, fid) ) continue; |
| 187 | 243 | printf("M %s :%d %s\n", zPerm, BLOBMARK(fid), pFile->zName); |
| 188 | 244 | } |
| 189 | 245 | manifest_cache_insert(p); |
| 190 | 246 | }else{ |
| 191 | - Stmt q3; | |
| 247 | + Stmt q4; | |
| 192 | 248 | int parent; |
| 193 | 249 | |
| 194 | - parent = db_column_int(&q2, 0); | |
| 250 | + parent = db_column_int(&q3, 0); | |
| 195 | 251 | printf("from :%d\n", COMMITMARK(parent)); |
| 196 | - db_prepare(&q3, | |
| 252 | + db_prepare(&q4, | |
| 197 | 253 | "SELECT pid FROM plink" |
| 198 | 254 | " WHERE cid=%d AND NOT isprim" |
| 199 | 255 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 200 | 256 | " ORDER BY pid", |
| 201 | 257 | ckinId); |
| 202 | - while( db_step(&q3)==SQLITE_ROW ){ | |
| 203 | - printf("merge :%d\n", COMMITMARK(db_column_int(&q3,0))); | |
| 258 | + while( db_step(&q4)==SQLITE_ROW ){ | |
| 259 | + printf("merge :%d\n", COMMITMARK(db_column_int(&q4,0))); | |
| 204 | 260 | } |
| 205 | - db_finalize(&q3); | |
| 261 | + db_finalize(&q4); | |
| 206 | 262 | |
| 207 | - db_prepare(&q3, | |
| 263 | + db_prepare(&q4, | |
| 208 | 264 | "SELECT filename.name, mlink.fid, mlink.mperm FROM mlink" |
| 209 | 265 | " JOIN filename ON filename.fnid=mlink.fnid" |
| 210 | 266 | " WHERE mlink.mid=%d", |
| 211 | 267 | parent |
| 212 | 268 | ); |
| 213 | - while( db_step(&q3)==SQLITE_ROW ){ | |
| 214 | - const char *zName = db_column_text(&q3,0); | |
| 215 | - int zNew = db_column_int(&q3,1); | |
| 216 | - int mPerm = db_column_int(&q3,2); | |
| 269 | + while( db_step(&q4)==SQLITE_ROW ){ | |
| 270 | + const char *zName = db_column_text(&q4,0); | |
| 271 | + int zNew = db_column_int(&q4,1); | |
| 272 | + int mPerm = db_column_int(&q4,2); | |
| 217 | 273 | if( zNew==0) |
| 218 | 274 | printf("D %s\n", zName); |
| 219 | 275 | else if( bag_find(&blobs, zNew) ) |
| 220 | 276 | printf("M %s :%d %s\n", mPerm ? "100755" : "100644", BLOBMARK(zNew), zName); |
| 221 | 277 | } |
| 222 | - db_finalize(&q3); | |
| 278 | + db_finalize(&q4); | |
| 223 | 279 | } |
| 224 | - db_finalize(&q2); | |
| 280 | + db_finalize(&q3); | |
| 225 | 281 | printf("\n"); |
| 226 | 282 | } |
| 283 | + db_finalize(&q2); | |
| 227 | 284 | db_finalize(&q); |
| 228 | 285 | bag_clear(&blobs); |
| 229 | 286 | manifest_cache_clear(); |
| 230 | 287 | |
| 231 | 288 | |
| @@ -253,6 +310,27 @@ | ||
| 253 | 310 | printf("data 0\n"); |
| 254 | 311 | fossil_free(zEncoded); |
| 255 | 312 | } |
| 256 | 313 | db_finalize(&q); |
| 257 | 314 | bag_clear(&vers); |
| 315 | + | |
| 316 | + if( markfile_out!=0 ){ | |
| 317 | + FILE *f; | |
| 318 | + f = fopen(markfile_out, "w"); | |
| 319 | + if( f == 0 ){ | |
| 320 | + fossil_panic("cannot open %s for writing", markfile_out); | |
| 321 | + } | |
| 322 | + db_prepare(&q, "SELECT rid FROM oldblob"); | |
| 323 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 324 | + fprintf(f, "b%d\n", db_column_int(&q, 0)); | |
| 325 | + } | |
| 326 | + db_finalize(&q); | |
| 327 | + db_prepare(&q, "SELECT rid FROM oldcommit"); | |
| 328 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 329 | + fprintf(f, "c%d\n", db_column_int(&q, 0)); | |
| 330 | + } | |
| 331 | + db_finalize(&q); | |
| 332 | + if( ferror(f)!=0 || fclose(f)!=0 ) { | |
| 333 | + fossil_panic("error while writing %s", markfile_out); | |
| 334 | + } | |
| 335 | + } | |
| 258 | 336 | } |
| 259 | 337 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -84,11 +84,11 @@ | |
| 84 | #define COMMITMARK(rid) ((rid) * 2 + 1) |
| 85 | |
| 86 | /* |
| 87 | ** COMMAND: export |
| 88 | ** |
| 89 | ** Usage: %fossil export --git ?REPOSITORY? |
| 90 | ** |
| 91 | ** Write an export of all check-ins to standard output. The export is |
| 92 | ** written in the git-fast-export file format assuming the --git option is |
| 93 | ** provided. The git-fast-export format is currently the only VCS |
| 94 | ** interchange format supported, though other formats may be added in |
| @@ -97,61 +97,117 @@ | |
| 97 | ** Run this command within a checkout. Or use the -R or --repository |
| 98 | ** option to specify a Fossil repository to be exported. |
| 99 | ** |
| 100 | ** Only check-ins are exported using --git. Git does not support tickets |
| 101 | ** or wiki or events or attachments, so none of those are exported. |
| 102 | */ |
| 103 | void export_cmd(void){ |
| 104 | Stmt q; |
| 105 | int i; |
| 106 | Bag blobs, vers; |
| 107 | bag_init(&blobs); |
| 108 | bag_init(&vers); |
| 109 | |
| 110 | find_option("git", 0, 0); /* Ignore the --git option for now */ |
| 111 | db_find_and_open_repository(0, 2); |
| 112 | verify_all_options(); |
| 113 | if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); } |
| 114 | |
| 115 | /* Step 1: Generate "blob" records for every artifact that is part |
| 116 | ** of a check-in |
| 117 | */ |
| 118 | fossil_binary_mode(stdout); |
| 119 | db_prepare(&q, "SELECT DISTINCT fid FROM mlink WHERE fid>0"); |
| 120 | while( db_step(&q)==SQLITE_ROW ){ |
| 121 | int rid = db_column_int(&q, 0); |
| 122 | Blob content; |
| 123 | content_get(rid, &content); |
| 124 | printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content)); |
| 125 | bag_insert(&blobs, rid); |
| 126 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 127 | printf("\n"); |
| 128 | blob_reset(&content); |
| 129 | } |
| 130 | db_finalize(&q); |
| 131 | |
| 132 | /* Output the commit records. |
| 133 | */ |
| 134 | db_prepare(&q, |
| 135 | "SELECT strftime('%%s',mtime), objid, coalesce(comment,ecomment)," |
| 136 | " coalesce(user,euser)," |
| 137 | " (SELECT value FROM tagxref WHERE rid=objid AND tagid=%d)" |
| 138 | " FROM event" |
| 139 | " WHERE type='ci'" |
| 140 | " ORDER BY mtime ASC", |
| 141 | TAG_BRANCH |
| 142 | ); |
| 143 | while( db_step(&q)==SQLITE_ROW ){ |
| 144 | Stmt q2; |
| 145 | const char *zSecondsSince1970 = db_column_text(&q, 0); |
| 146 | int ckinId = db_column_int(&q, 1); |
| 147 | const char *zComment = db_column_text(&q, 2); |
| 148 | const char *zUser = db_column_text(&q, 3); |
| 149 | const char *zBranch = db_column_text(&q, 4); |
| 150 | char *zBr; |
| 151 | |
| 152 | bag_insert(&vers, ckinId); |
| 153 | if( zBranch==0 ) zBranch = "trunk"; |
| 154 | zBr = mprintf("%s", zBranch); |
| 155 | for(i=0; zBr[i]; i++){ |
| 156 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 157 | } |
| @@ -160,12 +216,12 @@ | |
| 160 | printf("committer"); |
| 161 | print_person(zUser); |
| 162 | printf(" %s +0000\n", zSecondsSince1970); |
| 163 | if( zComment==0 ) zComment = "null comment"; |
| 164 | printf("data %d\n%s\n", (int)strlen(zComment), zComment); |
| 165 | db_prepare(&q2, "SELECT pid FROM plink WHERE cid=%d AND isprim", ckinId); |
| 166 | if( db_step(&q2) != SQLITE_ROW ){ |
| 167 | const char *zFromType; |
| 168 | Manifest *p; |
| 169 | ManifestFile *pFile; |
| 170 | |
| 171 | zFromType = "from"; |
| @@ -186,46 +242,47 @@ | |
| 186 | if( !bag_find(&blobs, fid) ) continue; |
| 187 | printf("M %s :%d %s\n", zPerm, BLOBMARK(fid), pFile->zName); |
| 188 | } |
| 189 | manifest_cache_insert(p); |
| 190 | }else{ |
| 191 | Stmt q3; |
| 192 | int parent; |
| 193 | |
| 194 | parent = db_column_int(&q2, 0); |
| 195 | printf("from :%d\n", COMMITMARK(parent)); |
| 196 | db_prepare(&q3, |
| 197 | "SELECT pid FROM plink" |
| 198 | " WHERE cid=%d AND NOT isprim" |
| 199 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 200 | " ORDER BY pid", |
| 201 | ckinId); |
| 202 | while( db_step(&q3)==SQLITE_ROW ){ |
| 203 | printf("merge :%d\n", COMMITMARK(db_column_int(&q3,0))); |
| 204 | } |
| 205 | db_finalize(&q3); |
| 206 | |
| 207 | db_prepare(&q3, |
| 208 | "SELECT filename.name, mlink.fid, mlink.mperm FROM mlink" |
| 209 | " JOIN filename ON filename.fnid=mlink.fnid" |
| 210 | " WHERE mlink.mid=%d", |
| 211 | parent |
| 212 | ); |
| 213 | while( db_step(&q3)==SQLITE_ROW ){ |
| 214 | const char *zName = db_column_text(&q3,0); |
| 215 | int zNew = db_column_int(&q3,1); |
| 216 | int mPerm = db_column_int(&q3,2); |
| 217 | if( zNew==0) |
| 218 | printf("D %s\n", zName); |
| 219 | else if( bag_find(&blobs, zNew) ) |
| 220 | printf("M %s :%d %s\n", mPerm ? "100755" : "100644", BLOBMARK(zNew), zName); |
| 221 | } |
| 222 | db_finalize(&q3); |
| 223 | } |
| 224 | db_finalize(&q2); |
| 225 | printf("\n"); |
| 226 | } |
| 227 | db_finalize(&q); |
| 228 | bag_clear(&blobs); |
| 229 | manifest_cache_clear(); |
| 230 | |
| 231 | |
| @@ -253,6 +310,27 @@ | |
| 253 | printf("data 0\n"); |
| 254 | fossil_free(zEncoded); |
| 255 | } |
| 256 | db_finalize(&q); |
| 257 | bag_clear(&vers); |
| 258 | } |
| 259 |
| --- src/export.c | |
| +++ src/export.c | |
| @@ -84,11 +84,11 @@ | |
| 84 | #define COMMITMARK(rid) ((rid) * 2 + 1) |
| 85 | |
| 86 | /* |
| 87 | ** COMMAND: export |
| 88 | ** |
| 89 | ** Usage: %fossil export --git ?options? ?REPOSITORY? |
| 90 | ** |
| 91 | ** Write an export of all check-ins to standard output. The export is |
| 92 | ** written in the git-fast-export file format assuming the --git option is |
| 93 | ** provided. The git-fast-export format is currently the only VCS |
| 94 | ** interchange format supported, though other formats may be added in |
| @@ -97,61 +97,117 @@ | |
| 97 | ** Run this command within a checkout. Or use the -R or --repository |
| 98 | ** option to specify a Fossil repository to be exported. |
| 99 | ** |
| 100 | ** Only check-ins are exported using --git. Git does not support tickets |
| 101 | ** or wiki or events or attachments, so none of those are exported. |
| 102 | ** |
| 103 | ** If the "--import-marks FILE" option is used, it contains a list of |
| 104 | ** rids to skip. |
| 105 | ** |
| 106 | ** If the "--export-marks FILE" option is used, the rid of all commits and |
| 107 | ** blobs written on exit for use with "--import-marks" on the next run. |
| 108 | */ |
| 109 | void export_cmd(void){ |
| 110 | Stmt q, q2; |
| 111 | int i; |
| 112 | Bag blobs, vers; |
| 113 | const char *markfile_in; |
| 114 | const char *markfile_out; |
| 115 | |
| 116 | bag_init(&blobs); |
| 117 | bag_init(&vers); |
| 118 | |
| 119 | find_option("git", 0, 0); /* Ignore the --git option for now */ |
| 120 | markfile_in = find_option("import-marks", 0, 1); |
| 121 | markfile_out = find_option("export-marks", 0, 1); |
| 122 | |
| 123 | db_find_and_open_repository(0, 2); |
| 124 | verify_all_options(); |
| 125 | if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); } |
| 126 | |
| 127 | db_multi_exec("CREATE TEMPORARY TABLE oldblob(rid INTEGER)"); |
| 128 | db_multi_exec("CREATE TEMPORARY TABLE oldcommit(rid INTEGER)"); |
| 129 | if( markfile_in!=0 ){ |
| 130 | Stmt qb,qc; |
| 131 | char line[100]; |
| 132 | FILE *f; |
| 133 | |
| 134 | f = fopen(markfile_in, "r"); |
| 135 | if( f==0 ){ |
| 136 | fossil_panic("cannot open %s for reading", markfile_in); |
| 137 | } |
| 138 | db_prepare(&qb, "INSERT INTO oldblob VALUES (:rid)"); |
| 139 | db_prepare(&qc, "INSERT INTO oldcommit VALUES (:rid)"); |
| 140 | while( fgets(line, sizeof(line), f)!=0 ){ |
| 141 | if( *line == 'b' ){ |
| 142 | db_bind_text(&qb, ":rid", line + 1); |
| 143 | db_step(&qb); |
| 144 | db_reset(&qb); |
| 145 | bag_insert(&blobs, atoi(line + 1)); |
| 146 | }else if( *line == 'c' ){ |
| 147 | db_bind_text(&qc, ":rid", line + 1); |
| 148 | db_step(&qc); |
| 149 | db_reset(&qc); |
| 150 | bag_insert(&vers, atoi(line + 1)); |
| 151 | }else{ |
| 152 | fossil_panic("bad input from %s: %s", markfile_in, line); |
| 153 | } |
| 154 | } |
| 155 | db_finalize(&qb); |
| 156 | db_finalize(&qc); |
| 157 | fclose(f); |
| 158 | } |
| 159 | |
| 160 | /* Step 1: Generate "blob" records for every artifact that is part |
| 161 | ** of a check-in |
| 162 | */ |
| 163 | fossil_binary_mode(stdout); |
| 164 | db_prepare(&q, |
| 165 | "SELECT DISTINCT fid FROM mlink" |
| 166 | " WHERE fid>0 AND NOT EXISTS(SELECT 1 FROM oldblob WHERE rid=fid)"); |
| 167 | db_prepare(&q2, "INSERT INTO oldblob VALUES (:rid)"); |
| 168 | while( db_step(&q)==SQLITE_ROW ){ |
| 169 | int rid = db_column_int(&q, 0); |
| 170 | Blob content; |
| 171 | content_get(rid, &content); |
| 172 | db_bind_int(&q2, ":rid", rid); |
| 173 | db_step(&q2); |
| 174 | db_reset(&q2); |
| 175 | printf("blob\nmark :%d\ndata %d\n", BLOBMARK(rid), blob_size(&content)); |
| 176 | bag_insert(&blobs, rid); |
| 177 | fwrite(blob_buffer(&content), 1, blob_size(&content), stdout); |
| 178 | printf("\n"); |
| 179 | blob_reset(&content); |
| 180 | } |
| 181 | db_finalize(&q); |
| 182 | db_finalize(&q2); |
| 183 | |
| 184 | /* Output the commit records. |
| 185 | */ |
| 186 | db_prepare(&q, |
| 187 | "SELECT strftime('%%s',mtime), objid, coalesce(comment,ecomment)," |
| 188 | " coalesce(user,euser)," |
| 189 | " (SELECT value FROM tagxref WHERE rid=objid AND tagid=%d)" |
| 190 | " FROM event" |
| 191 | " WHERE type='ci' AND NOT EXISTS (SELECT 1 FROM oldcommit WHERE objid=rid)" |
| 192 | " ORDER BY mtime ASC", |
| 193 | TAG_BRANCH |
| 194 | ); |
| 195 | db_prepare(&q2, "INSERT INTO oldcommit VALUES (:rid)"); |
| 196 | while( db_step(&q)==SQLITE_ROW ){ |
| 197 | Stmt q3; |
| 198 | const char *zSecondsSince1970 = db_column_text(&q, 0); |
| 199 | int ckinId = db_column_int(&q, 1); |
| 200 | const char *zComment = db_column_text(&q, 2); |
| 201 | const char *zUser = db_column_text(&q, 3); |
| 202 | const char *zBranch = db_column_text(&q, 4); |
| 203 | char *zBr; |
| 204 | |
| 205 | bag_insert(&vers, ckinId); |
| 206 | db_bind_int(&q2, ":rid", ckinId); |
| 207 | db_step(&q2); |
| 208 | db_reset(&q2); |
| 209 | if( zBranch==0 ) zBranch = "trunk"; |
| 210 | zBr = mprintf("%s", zBranch); |
| 211 | for(i=0; zBr[i]; i++){ |
| 212 | if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_'; |
| 213 | } |
| @@ -160,12 +216,12 @@ | |
| 216 | printf("committer"); |
| 217 | print_person(zUser); |
| 218 | printf(" %s +0000\n", zSecondsSince1970); |
| 219 | if( zComment==0 ) zComment = "null comment"; |
| 220 | printf("data %d\n%s\n", (int)strlen(zComment), zComment); |
| 221 | db_prepare(&q3, "SELECT pid FROM plink WHERE cid=%d AND isprim", ckinId); |
| 222 | if( db_step(&q3) != SQLITE_ROW ){ |
| 223 | const char *zFromType; |
| 224 | Manifest *p; |
| 225 | ManifestFile *pFile; |
| 226 | |
| 227 | zFromType = "from"; |
| @@ -186,46 +242,47 @@ | |
| 242 | if( !bag_find(&blobs, fid) ) continue; |
| 243 | printf("M %s :%d %s\n", zPerm, BLOBMARK(fid), pFile->zName); |
| 244 | } |
| 245 | manifest_cache_insert(p); |
| 246 | }else{ |
| 247 | Stmt q4; |
| 248 | int parent; |
| 249 | |
| 250 | parent = db_column_int(&q3, 0); |
| 251 | printf("from :%d\n", COMMITMARK(parent)); |
| 252 | db_prepare(&q4, |
| 253 | "SELECT pid FROM plink" |
| 254 | " WHERE cid=%d AND NOT isprim" |
| 255 | " AND NOT EXISTS(SELECT 1 FROM phantom WHERE rid=pid)" |
| 256 | " ORDER BY pid", |
| 257 | ckinId); |
| 258 | while( db_step(&q4)==SQLITE_ROW ){ |
| 259 | printf("merge :%d\n", COMMITMARK(db_column_int(&q4,0))); |
| 260 | } |
| 261 | db_finalize(&q4); |
| 262 | |
| 263 | db_prepare(&q4, |
| 264 | "SELECT filename.name, mlink.fid, mlink.mperm FROM mlink" |
| 265 | " JOIN filename ON filename.fnid=mlink.fnid" |
| 266 | " WHERE mlink.mid=%d", |
| 267 | parent |
| 268 | ); |
| 269 | while( db_step(&q4)==SQLITE_ROW ){ |
| 270 | const char *zName = db_column_text(&q4,0); |
| 271 | int zNew = db_column_int(&q4,1); |
| 272 | int mPerm = db_column_int(&q4,2); |
| 273 | if( zNew==0) |
| 274 | printf("D %s\n", zName); |
| 275 | else if( bag_find(&blobs, zNew) ) |
| 276 | printf("M %s :%d %s\n", mPerm ? "100755" : "100644", BLOBMARK(zNew), zName); |
| 277 | } |
| 278 | db_finalize(&q4); |
| 279 | } |
| 280 | db_finalize(&q3); |
| 281 | printf("\n"); |
| 282 | } |
| 283 | db_finalize(&q2); |
| 284 | db_finalize(&q); |
| 285 | bag_clear(&blobs); |
| 286 | manifest_cache_clear(); |
| 287 | |
| 288 | |
| @@ -253,6 +310,27 @@ | |
| 310 | printf("data 0\n"); |
| 311 | fossil_free(zEncoded); |
| 312 | } |
| 313 | db_finalize(&q); |
| 314 | bag_clear(&vers); |
| 315 | |
| 316 | if( markfile_out!=0 ){ |
| 317 | FILE *f; |
| 318 | f = fopen(markfile_out, "w"); |
| 319 | if( f == 0 ){ |
| 320 | fossil_panic("cannot open %s for writing", markfile_out); |
| 321 | } |
| 322 | db_prepare(&q, "SELECT rid FROM oldblob"); |
| 323 | while( db_step(&q)==SQLITE_ROW ){ |
| 324 | fprintf(f, "b%d\n", db_column_int(&q, 0)); |
| 325 | } |
| 326 | db_finalize(&q); |
| 327 | db_prepare(&q, "SELECT rid FROM oldcommit"); |
| 328 | while( db_step(&q)==SQLITE_ROW ){ |
| 329 | fprintf(f, "c%d\n", db_column_int(&q, 0)); |
| 330 | } |
| 331 | db_finalize(&q); |
| 332 | if( ferror(f)!=0 || fclose(f)!=0 ) { |
| 333 | fossil_panic("error while writing %s", markfile_out); |
| 334 | } |
| 335 | } |
| 336 | } |
| 337 |