Fossil SCM

Do not use the --input-marks option with "git fast-import". Instead, remember older Git-names and insert them directly into the fast-import stream.

drh 2019-03-17 00:02 trunk
Commit 8e6f3ced08278afbd646a74e91eaea3ff37695eb588c22b64dbe00662da9edcf
1 file changed +46 -41
+46 -41
--- src/export.c
+++ src/export.c
@@ -936,37 +936,42 @@
936936
zOut[j] = 0;
937937
return zOut;
938938
}
939939
940940
/*
941
-** Locate the mark for a UUID.
941
+** Find the Git-name corresponding to the Fossil-name zUuid.
942942
**
943943
** If the mark does not exist and if the bCreate flag is false, then
944
-** return 0. If the mark does not exist and the bCreate flag is true,
944
+** return NULL. If the mark does not exist and the bCreate flag is true,
945945
** then create the mark.
946
+**
947
+** The string returned is obtained from fossil_malloc() and should
948
+** be freed by the caller.
946949
*/
947
-static int gitmirror_find_mark(const char *zUuid, int bCreate){
948
- int iMark;
950
+static char *gitmirror_find_mark(const char *zUuid, int bCreate){
949951
static Stmt sFind, sIns;
950952
db_static_prepare(&sFind,
951
- "SELECT id FROM mirror.mmark WHERE uuid=:uuid"
953
+ "SELECT coalesce(githash,printf(':%%d',id))"
954
+ " FROM mirror.mmark WHERE uuid=:uuid"
952955
);
953956
db_bind_text(&sFind, ":uuid", zUuid);
954957
if( db_step(&sFind)==SQLITE_ROW ){
955
- iMark = db_column_int(&sFind, 0);
958
+ char *zMark = fossil_strdup(db_column_text(&sFind, 0));
956959
db_reset(&sFind);
957
- return iMark;
960
+ return zMark;
958961
}
959962
db_reset(&sFind);
960
- if( !bCreate ) return 0;
963
+ if( !bCreate ){
964
+ return 0;
965
+ }
961966
db_static_prepare(&sIns,
962967
"INSERT INTO mirror.mmark(uuid) VALUES(:uuid)"
963968
);
964969
db_bind_text(&sIns, ":uuid", zUuid);
965970
db_step(&sIns);
966971
db_reset(&sIns);
967
- return db_last_insert_rowid();
972
+ return mprintf(":%d", db_last_insert_rowid());
968973
}
969974
970975
/* This is the SHA3-256 hash of an empty file */
971976
static const char zEmptySha3[] =
972977
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
@@ -980,11 +985,11 @@
980985
** But files that are missing from the repository but have not been officially
981986
** shunned cause an error return. Except, if bPhantomOk is true, then missing
982987
** files are replaced by an empty file.
983988
*/
984989
static int gitmirror_send_file(FILE *xCmd, const char *zUuid, int bPhantomOk){
985
- int iMark;
990
+ char *zMark;
986991
int rid;
987992
int rc;
988993
Blob data;
989994
rid = fast_uuid_to_rid(zUuid);
990995
if( rid<0 ){
@@ -1004,14 +1009,17 @@
10041009
}else{
10051010
return 1;
10061011
}
10071012
}
10081013
}
1009
- iMark = gitmirror_find_mark(zUuid, 1);
1010
- fprintf(xCmd, "blob\nmark :%d\ndata %d\n", iMark, blob_size(&data));
1011
- fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
1012
- fprintf(xCmd, "\n");
1014
+ zMark = gitmirror_find_mark(zUuid, 1);
1015
+ if( zMark[0]==':' ){
1016
+ fprintf(xCmd, "blob\nmark %s\ndata %d\n", zMark, blob_size(&data));
1017
+ fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
1018
+ fprintf(xCmd, "\n");
1019
+ }
1020
+ fossil_free(zMark);
10131021
blob_reset(&data);
10141022
return 0;
10151023
}
10161024
10171025
/*
@@ -1039,11 +1047,11 @@
10391047
Manifest *pMan; /* The check-in to be output */
10401048
int i; /* Loop counter */
10411049
int iParent; /* Which immediate ancestor is primary. -1 for none */
10421050
Stmt q; /* An SQL query */
10431051
char *zBranch; /* The branch of the check-in */
1044
- int iMark; /* The mark for the check-in */
1052
+ char *zMark; /* The Git-name of the check-in */
10451053
Blob sql; /* String of SQL for part of the query */
10461054
Blob comment; /* The comment text for the check-in */
10471055
int nErr = 0; /* Number of errors */
10481056
int bPhantomOk; /* True if phantom files should be ignored */
10491057
@@ -1056,21 +1064,22 @@
10561064
}
10571065
10581066
/* Check to see if any parent logins have not yet been processed, and
10591067
** if so, create them */
10601068
for(i=0; i<pMan->nParent; i++){
1061
- int iMark = gitmirror_find_mark(pMan->azParent[i], 0);
1062
- if( iMark<=0 ){
1069
+ char *zPMark = gitmirror_find_mark(pMan->azParent[i], 0);
1070
+ if( zPMark==0 ){
10631071
int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
10641072
pMan->azParent[i]);
10651073
int rc = gitmirror_send_checkin(xCmd, prid, pMan->azParent[i],
10661074
pnLimit, fManifest);
10671075
if( rc || *pnLimit<=0 ){
10681076
manifest_destroy(pMan);
10691077
return 1;
10701078
}
10711079
}
1080
+ fossil_free(zPMark);
10721081
}
10731082
10741083
/* Ignore phantom files on check-ins that are over one year old */
10751084
bPhantomOk = db_int(0, "SELECT %.6f<julianday('now','-1 year')",
10761085
pMan->rDate);
@@ -1113,12 +1122,13 @@
11131122
}
11141123
11151124
/* Export the check-in */
11161125
fprintf(xCmd, "commit refs/heads/%s\n", zBranch);
11171126
fossil_free(zBranch);
1118
- iMark = gitmirror_find_mark(zUuid, 1);
1119
- fprintf(xCmd, "mark :%d\n", iMark);
1127
+ zMark = gitmirror_find_mark(zUuid,1);
1128
+ fprintf(xCmd, "mark %s\n", zMark);
1129
+ fossil_free(zMark);
11201130
fprintf(xCmd, "committer %s <%[email protected]> %lld +0000\n",
11211131
pMan->zUser, pMan->zUser,
11221132
(sqlite3_int64)((pMan->rDate-2440587.5)*86400.0)
11231133
);
11241134
blob_init(&comment, pMan->zComment, -1);
@@ -1128,18 +1138,19 @@
11281138
blob_appendf(&comment, "\n\nFossilOrigin-Name: %s", zUuid);
11291139
fprintf(xCmd, "data %d\n%s\n", blob_size(&comment), blob_str(&comment));
11301140
blob_reset(&comment);
11311141
iParent = -1; /* Which ancestor is the primary parent */
11321142
for(i=0; i<pMan->nParent; i++){
1133
- int iOther = gitmirror_find_mark(pMan->azParent[i], 0);
1134
- if( iOther==0 ) continue;
1143
+ char *zOther = gitmirror_find_mark(pMan->azParent[i], 0);
1144
+ if( zOther==0 ) continue;
11351145
if( iParent<0 ){
11361146
iParent = i;
1137
- fprintf(xCmd, "from :%d\n", iOther);
1147
+ fprintf(xCmd, "from %s\n", zOther);
11381148
}else{
1139
- fprintf(xCmd, "merge :%d\n", iOther);
1149
+ fprintf(xCmd, "merge %s\n", zOther);
11401150
}
1151
+ fossil_free(zOther);
11411152
}
11421153
if( iParent>=0 ){
11431154
db_prepare(&q,
11441155
"SELECT filename FROM files_of_checkin(%Q)"
11451156
" EXCEPT SELECT filename FROM files_of_checkin(%Q)",
@@ -1159,27 +1170,29 @@
11591170
blob_append_sql(&sql,
11601171
" EXCEPT SELECT filename, uuid, perm FROM files_of_checkin(%Q)",
11611172
pMan->azParent[0]);
11621173
}
11631174
db_prepare(&q,
1164
- "SELECT x.filename, x.perm, mmark.id FROM (%s) AS x, mirror.mmark"
1175
+ "SELECT x.filename, x.perm,"
1176
+ " coalesce(mmark.githash,printf(':%%d',mmark.id))"
1177
+ " FROM (%s) AS x, mirror.mmark"
11651178
" WHERE mmark.uuid=x.uuid",
11661179
blob_sql_text(&sql)
11671180
);
11681181
blob_reset(&sql);
11691182
while( db_step(&q)==SQLITE_ROW ){
11701183
const char *zFilename = db_column_text(&q,0);
11711184
const char *zMode = db_column_text(&q,1);
1172
- int iMark = db_column_int(&q,2);
1185
+ const char *zMark = db_column_text(&q,2);
11731186
const char *zGitMode = "100644";
11741187
char *zFNQuoted = 0;
11751188
if( zMode ){
11761189
if( strchr(zMode,'x') ) zGitMode = "100755";
11771190
if( strchr(zMode,'l') ) zGitMode = "120000";
11781191
}
11791192
zFNQuoted = gitmirror_quote_filename_if_needed(zFilename);
1180
- fprintf(xCmd,"M %s :%d %s\n", zGitMode, iMark, zFNQuoted);
1193
+ fprintf(xCmd,"M %s %s %s\n", zGitMode, zMark, zFNQuoted);
11811194
fossil_free(zFNQuoted);
11821195
}
11831196
db_finalize(&q);
11841197
11851198
/* Include Fossil-generated auxiliary files in the check-in */
@@ -1224,11 +1237,11 @@
12241237
double rEnd; /* time of most recent export */
12251238
int rc; /* Result code */
12261239
int bForce; /* Do the export and sync even if no changes*/
12271240
int fManifest; /* Current "manifest" setting */
12281241
FILE *xCmd; /* Pipe to the "git fast-import" command */
1229
- FILE *pIn, *pOut; /* Git mark files */
1242
+ FILE *pMarks; /* Git mark files */
12301243
Stmt q; /* Queries */
12311244
char zLine[200]; /* One line of a mark file */
12321245
12331246
zDebug = find_option("debug",0,1);
12341247
db_find_and_open_repository(0, 0);
@@ -1334,12 +1347,11 @@
13341347
xCmd = fopen(zDebug, "wb");
13351348
if( xCmd==0 ) fossil_fatal("cannot open file \"%s\" for writing", zDebug);
13361349
}
13371350
}else{
13381351
zCmd = mprintf("git fast-import"
1339
- " --import-marks-if-exists=.mirror_state/in"
1340
- " --export-marks=.mirror_state/out"
1352
+ " --export-marks=.mirror_state/marks.txt"
13411353
" --quiet --done");
13421354
gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
13431355
xCmd = popen(zCmd, "w");
13441356
if( zCmd==0 ){
13451357
fossil_fatal("cannot start the \"git fast-import\" command");
@@ -1388,18 +1400,14 @@
13881400
nTotal-nLimit, zMirror);
13891401
13901402
/* Read the export-marks file. Transfer the new marks over into
13911403
** the import-marks file.
13921404
*/
1393
- pOut = fopen(".mirror_state/out", "rb");
1394
- if( pOut ){
1395
- pIn = fopen(".mirror_state/in", "ab");
1396
- if( pIn==0 ){
1397
- fossil_fatal("cannot open %s/.mirror_state/in for appending", zMirror);
1398
- }
1405
+ pMarks = fopen(".mirror_state/marks.txt", "rb");
1406
+ if( pMarks ){
13991407
db_prepare(&q, "UPDATE mirror.mmark SET githash=:githash WHERE id=:id");
1400
- while( fgets(zLine, sizeof(zLine), pOut) ){
1408
+ while( fgets(zLine, sizeof(zLine), pMarks) ){
14011409
int j, k;
14021410
if( zLine[0]!=':' ) continue;
14031411
db_bind_int(&q, ":id", atoi(zLine+1));
14041412
for(j=1; zLine[j] && zLine[j]!=' '; j++){}
14051413
if( zLine[j]!=' ' ) continue;
@@ -1408,17 +1416,14 @@
14081416
for(k=j; fossil_isalnum(zLine[k]); k++){}
14091417
zLine[k] = 0;
14101418
db_bind_text(&q, ":githash", &zLine[j]);
14111419
db_step(&q);
14121420
db_reset(&q);
1413
- zLine[k] = '\n';
1414
- fputs(zLine, pIn);
14151421
}
14161422
db_finalize(&q);
1417
- fclose(pOut);
1418
- fclose(pIn);
1419
- file_delete(".mirror_state/out");
1423
+ fclose(pMarks);
1424
+ file_delete(".mirror_state/marks.txt");
14201425
}else{
14211426
fossil_fatal("git fast-import didn't generate a marks file!");
14221427
}
14231428
db_multi_exec(
14241429
"CREATE INDEX IF NOT EXISTS mirror.mmarkx1 ON mmark(githash);"
14251430
--- src/export.c
+++ src/export.c
@@ -936,37 +936,42 @@
936 zOut[j] = 0;
937 return zOut;
938 }
939
940 /*
941 ** Locate the mark for a UUID.
942 **
943 ** If the mark does not exist and if the bCreate flag is false, then
944 ** return 0. If the mark does not exist and the bCreate flag is true,
945 ** then create the mark.
 
 
 
946 */
947 static int gitmirror_find_mark(const char *zUuid, int bCreate){
948 int iMark;
949 static Stmt sFind, sIns;
950 db_static_prepare(&sFind,
951 "SELECT id FROM mirror.mmark WHERE uuid=:uuid"
 
952 );
953 db_bind_text(&sFind, ":uuid", zUuid);
954 if( db_step(&sFind)==SQLITE_ROW ){
955 iMark = db_column_int(&sFind, 0);
956 db_reset(&sFind);
957 return iMark;
958 }
959 db_reset(&sFind);
960 if( !bCreate ) return 0;
 
 
961 db_static_prepare(&sIns,
962 "INSERT INTO mirror.mmark(uuid) VALUES(:uuid)"
963 );
964 db_bind_text(&sIns, ":uuid", zUuid);
965 db_step(&sIns);
966 db_reset(&sIns);
967 return db_last_insert_rowid();
968 }
969
970 /* This is the SHA3-256 hash of an empty file */
971 static const char zEmptySha3[] =
972 "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
@@ -980,11 +985,11 @@
980 ** But files that are missing from the repository but have not been officially
981 ** shunned cause an error return. Except, if bPhantomOk is true, then missing
982 ** files are replaced by an empty file.
983 */
984 static int gitmirror_send_file(FILE *xCmd, const char *zUuid, int bPhantomOk){
985 int iMark;
986 int rid;
987 int rc;
988 Blob data;
989 rid = fast_uuid_to_rid(zUuid);
990 if( rid<0 ){
@@ -1004,14 +1009,17 @@
1004 }else{
1005 return 1;
1006 }
1007 }
1008 }
1009 iMark = gitmirror_find_mark(zUuid, 1);
1010 fprintf(xCmd, "blob\nmark :%d\ndata %d\n", iMark, blob_size(&data));
1011 fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
1012 fprintf(xCmd, "\n");
 
 
 
1013 blob_reset(&data);
1014 return 0;
1015 }
1016
1017 /*
@@ -1039,11 +1047,11 @@
1039 Manifest *pMan; /* The check-in to be output */
1040 int i; /* Loop counter */
1041 int iParent; /* Which immediate ancestor is primary. -1 for none */
1042 Stmt q; /* An SQL query */
1043 char *zBranch; /* The branch of the check-in */
1044 int iMark; /* The mark for the check-in */
1045 Blob sql; /* String of SQL for part of the query */
1046 Blob comment; /* The comment text for the check-in */
1047 int nErr = 0; /* Number of errors */
1048 int bPhantomOk; /* True if phantom files should be ignored */
1049
@@ -1056,21 +1064,22 @@
1056 }
1057
1058 /* Check to see if any parent logins have not yet been processed, and
1059 ** if so, create them */
1060 for(i=0; i<pMan->nParent; i++){
1061 int iMark = gitmirror_find_mark(pMan->azParent[i], 0);
1062 if( iMark<=0 ){
1063 int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
1064 pMan->azParent[i]);
1065 int rc = gitmirror_send_checkin(xCmd, prid, pMan->azParent[i],
1066 pnLimit, fManifest);
1067 if( rc || *pnLimit<=0 ){
1068 manifest_destroy(pMan);
1069 return 1;
1070 }
1071 }
 
1072 }
1073
1074 /* Ignore phantom files on check-ins that are over one year old */
1075 bPhantomOk = db_int(0, "SELECT %.6f<julianday('now','-1 year')",
1076 pMan->rDate);
@@ -1113,12 +1122,13 @@
1113 }
1114
1115 /* Export the check-in */
1116 fprintf(xCmd, "commit refs/heads/%s\n", zBranch);
1117 fossil_free(zBranch);
1118 iMark = gitmirror_find_mark(zUuid, 1);
1119 fprintf(xCmd, "mark :%d\n", iMark);
 
1120 fprintf(xCmd, "committer %s <%[email protected]> %lld +0000\n",
1121 pMan->zUser, pMan->zUser,
1122 (sqlite3_int64)((pMan->rDate-2440587.5)*86400.0)
1123 );
1124 blob_init(&comment, pMan->zComment, -1);
@@ -1128,18 +1138,19 @@
1128 blob_appendf(&comment, "\n\nFossilOrigin-Name: %s", zUuid);
1129 fprintf(xCmd, "data %d\n%s\n", blob_size(&comment), blob_str(&comment));
1130 blob_reset(&comment);
1131 iParent = -1; /* Which ancestor is the primary parent */
1132 for(i=0; i<pMan->nParent; i++){
1133 int iOther = gitmirror_find_mark(pMan->azParent[i], 0);
1134 if( iOther==0 ) continue;
1135 if( iParent<0 ){
1136 iParent = i;
1137 fprintf(xCmd, "from :%d\n", iOther);
1138 }else{
1139 fprintf(xCmd, "merge :%d\n", iOther);
1140 }
 
1141 }
1142 if( iParent>=0 ){
1143 db_prepare(&q,
1144 "SELECT filename FROM files_of_checkin(%Q)"
1145 " EXCEPT SELECT filename FROM files_of_checkin(%Q)",
@@ -1159,27 +1170,29 @@
1159 blob_append_sql(&sql,
1160 " EXCEPT SELECT filename, uuid, perm FROM files_of_checkin(%Q)",
1161 pMan->azParent[0]);
1162 }
1163 db_prepare(&q,
1164 "SELECT x.filename, x.perm, mmark.id FROM (%s) AS x, mirror.mmark"
 
 
1165 " WHERE mmark.uuid=x.uuid",
1166 blob_sql_text(&sql)
1167 );
1168 blob_reset(&sql);
1169 while( db_step(&q)==SQLITE_ROW ){
1170 const char *zFilename = db_column_text(&q,0);
1171 const char *zMode = db_column_text(&q,1);
1172 int iMark = db_column_int(&q,2);
1173 const char *zGitMode = "100644";
1174 char *zFNQuoted = 0;
1175 if( zMode ){
1176 if( strchr(zMode,'x') ) zGitMode = "100755";
1177 if( strchr(zMode,'l') ) zGitMode = "120000";
1178 }
1179 zFNQuoted = gitmirror_quote_filename_if_needed(zFilename);
1180 fprintf(xCmd,"M %s :%d %s\n", zGitMode, iMark, zFNQuoted);
1181 fossil_free(zFNQuoted);
1182 }
1183 db_finalize(&q);
1184
1185 /* Include Fossil-generated auxiliary files in the check-in */
@@ -1224,11 +1237,11 @@
1224 double rEnd; /* time of most recent export */
1225 int rc; /* Result code */
1226 int bForce; /* Do the export and sync even if no changes*/
1227 int fManifest; /* Current "manifest" setting */
1228 FILE *xCmd; /* Pipe to the "git fast-import" command */
1229 FILE *pIn, *pOut; /* Git mark files */
1230 Stmt q; /* Queries */
1231 char zLine[200]; /* One line of a mark file */
1232
1233 zDebug = find_option("debug",0,1);
1234 db_find_and_open_repository(0, 0);
@@ -1334,12 +1347,11 @@
1334 xCmd = fopen(zDebug, "wb");
1335 if( xCmd==0 ) fossil_fatal("cannot open file \"%s\" for writing", zDebug);
1336 }
1337 }else{
1338 zCmd = mprintf("git fast-import"
1339 " --import-marks-if-exists=.mirror_state/in"
1340 " --export-marks=.mirror_state/out"
1341 " --quiet --done");
1342 gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
1343 xCmd = popen(zCmd, "w");
1344 if( zCmd==0 ){
1345 fossil_fatal("cannot start the \"git fast-import\" command");
@@ -1388,18 +1400,14 @@
1388 nTotal-nLimit, zMirror);
1389
1390 /* Read the export-marks file. Transfer the new marks over into
1391 ** the import-marks file.
1392 */
1393 pOut = fopen(".mirror_state/out", "rb");
1394 if( pOut ){
1395 pIn = fopen(".mirror_state/in", "ab");
1396 if( pIn==0 ){
1397 fossil_fatal("cannot open %s/.mirror_state/in for appending", zMirror);
1398 }
1399 db_prepare(&q, "UPDATE mirror.mmark SET githash=:githash WHERE id=:id");
1400 while( fgets(zLine, sizeof(zLine), pOut) ){
1401 int j, k;
1402 if( zLine[0]!=':' ) continue;
1403 db_bind_int(&q, ":id", atoi(zLine+1));
1404 for(j=1; zLine[j] && zLine[j]!=' '; j++){}
1405 if( zLine[j]!=' ' ) continue;
@@ -1408,17 +1416,14 @@
1408 for(k=j; fossil_isalnum(zLine[k]); k++){}
1409 zLine[k] = 0;
1410 db_bind_text(&q, ":githash", &zLine[j]);
1411 db_step(&q);
1412 db_reset(&q);
1413 zLine[k] = '\n';
1414 fputs(zLine, pIn);
1415 }
1416 db_finalize(&q);
1417 fclose(pOut);
1418 fclose(pIn);
1419 file_delete(".mirror_state/out");
1420 }else{
1421 fossil_fatal("git fast-import didn't generate a marks file!");
1422 }
1423 db_multi_exec(
1424 "CREATE INDEX IF NOT EXISTS mirror.mmarkx1 ON mmark(githash);"
1425
--- src/export.c
+++ src/export.c
@@ -936,37 +936,42 @@
936 zOut[j] = 0;
937 return zOut;
938 }
939
940 /*
941 ** Find the Git-name corresponding to the Fossil-name zUuid.
942 **
943 ** If the mark does not exist and if the bCreate flag is false, then
944 ** return NULL. If the mark does not exist and the bCreate flag is true,
945 ** then create the mark.
946 **
947 ** The string returned is obtained from fossil_malloc() and should
948 ** be freed by the caller.
949 */
950 static char *gitmirror_find_mark(const char *zUuid, int bCreate){
 
951 static Stmt sFind, sIns;
952 db_static_prepare(&sFind,
953 "SELECT coalesce(githash,printf(':%%d',id))"
954 " FROM mirror.mmark WHERE uuid=:uuid"
955 );
956 db_bind_text(&sFind, ":uuid", zUuid);
957 if( db_step(&sFind)==SQLITE_ROW ){
958 char *zMark = fossil_strdup(db_column_text(&sFind, 0));
959 db_reset(&sFind);
960 return zMark;
961 }
962 db_reset(&sFind);
963 if( !bCreate ){
964 return 0;
965 }
966 db_static_prepare(&sIns,
967 "INSERT INTO mirror.mmark(uuid) VALUES(:uuid)"
968 );
969 db_bind_text(&sIns, ":uuid", zUuid);
970 db_step(&sIns);
971 db_reset(&sIns);
972 return mprintf(":%d", db_last_insert_rowid());
973 }
974
975 /* This is the SHA3-256 hash of an empty file */
976 static const char zEmptySha3[] =
977 "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
@@ -980,11 +985,11 @@
985 ** But files that are missing from the repository but have not been officially
986 ** shunned cause an error return. Except, if bPhantomOk is true, then missing
987 ** files are replaced by an empty file.
988 */
989 static int gitmirror_send_file(FILE *xCmd, const char *zUuid, int bPhantomOk){
990 char *zMark;
991 int rid;
992 int rc;
993 Blob data;
994 rid = fast_uuid_to_rid(zUuid);
995 if( rid<0 ){
@@ -1004,14 +1009,17 @@
1009 }else{
1010 return 1;
1011 }
1012 }
1013 }
1014 zMark = gitmirror_find_mark(zUuid, 1);
1015 if( zMark[0]==':' ){
1016 fprintf(xCmd, "blob\nmark %s\ndata %d\n", zMark, blob_size(&data));
1017 fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
1018 fprintf(xCmd, "\n");
1019 }
1020 fossil_free(zMark);
1021 blob_reset(&data);
1022 return 0;
1023 }
1024
1025 /*
@@ -1039,11 +1047,11 @@
1047 Manifest *pMan; /* The check-in to be output */
1048 int i; /* Loop counter */
1049 int iParent; /* Which immediate ancestor is primary. -1 for none */
1050 Stmt q; /* An SQL query */
1051 char *zBranch; /* The branch of the check-in */
1052 char *zMark; /* The Git-name of the check-in */
1053 Blob sql; /* String of SQL for part of the query */
1054 Blob comment; /* The comment text for the check-in */
1055 int nErr = 0; /* Number of errors */
1056 int bPhantomOk; /* True if phantom files should be ignored */
1057
@@ -1056,21 +1064,22 @@
1064 }
1065
1066 /* Check to see if any parent logins have not yet been processed, and
1067 ** if so, create them */
1068 for(i=0; i<pMan->nParent; i++){
1069 char *zPMark = gitmirror_find_mark(pMan->azParent[i], 0);
1070 if( zPMark==0 ){
1071 int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
1072 pMan->azParent[i]);
1073 int rc = gitmirror_send_checkin(xCmd, prid, pMan->azParent[i],
1074 pnLimit, fManifest);
1075 if( rc || *pnLimit<=0 ){
1076 manifest_destroy(pMan);
1077 return 1;
1078 }
1079 }
1080 fossil_free(zPMark);
1081 }
1082
1083 /* Ignore phantom files on check-ins that are over one year old */
1084 bPhantomOk = db_int(0, "SELECT %.6f<julianday('now','-1 year')",
1085 pMan->rDate);
@@ -1113,12 +1122,13 @@
1122 }
1123
1124 /* Export the check-in */
1125 fprintf(xCmd, "commit refs/heads/%s\n", zBranch);
1126 fossil_free(zBranch);
1127 zMark = gitmirror_find_mark(zUuid,1);
1128 fprintf(xCmd, "mark %s\n", zMark);
1129 fossil_free(zMark);
1130 fprintf(xCmd, "committer %s <%[email protected]> %lld +0000\n",
1131 pMan->zUser, pMan->zUser,
1132 (sqlite3_int64)((pMan->rDate-2440587.5)*86400.0)
1133 );
1134 blob_init(&comment, pMan->zComment, -1);
@@ -1128,18 +1138,19 @@
1138 blob_appendf(&comment, "\n\nFossilOrigin-Name: %s", zUuid);
1139 fprintf(xCmd, "data %d\n%s\n", blob_size(&comment), blob_str(&comment));
1140 blob_reset(&comment);
1141 iParent = -1; /* Which ancestor is the primary parent */
1142 for(i=0; i<pMan->nParent; i++){
1143 char *zOther = gitmirror_find_mark(pMan->azParent[i], 0);
1144 if( zOther==0 ) continue;
1145 if( iParent<0 ){
1146 iParent = i;
1147 fprintf(xCmd, "from %s\n", zOther);
1148 }else{
1149 fprintf(xCmd, "merge %s\n", zOther);
1150 }
1151 fossil_free(zOther);
1152 }
1153 if( iParent>=0 ){
1154 db_prepare(&q,
1155 "SELECT filename FROM files_of_checkin(%Q)"
1156 " EXCEPT SELECT filename FROM files_of_checkin(%Q)",
@@ -1159,27 +1170,29 @@
1170 blob_append_sql(&sql,
1171 " EXCEPT SELECT filename, uuid, perm FROM files_of_checkin(%Q)",
1172 pMan->azParent[0]);
1173 }
1174 db_prepare(&q,
1175 "SELECT x.filename, x.perm,"
1176 " coalesce(mmark.githash,printf(':%%d',mmark.id))"
1177 " FROM (%s) AS x, mirror.mmark"
1178 " WHERE mmark.uuid=x.uuid",
1179 blob_sql_text(&sql)
1180 );
1181 blob_reset(&sql);
1182 while( db_step(&q)==SQLITE_ROW ){
1183 const char *zFilename = db_column_text(&q,0);
1184 const char *zMode = db_column_text(&q,1);
1185 const char *zMark = db_column_text(&q,2);
1186 const char *zGitMode = "100644";
1187 char *zFNQuoted = 0;
1188 if( zMode ){
1189 if( strchr(zMode,'x') ) zGitMode = "100755";
1190 if( strchr(zMode,'l') ) zGitMode = "120000";
1191 }
1192 zFNQuoted = gitmirror_quote_filename_if_needed(zFilename);
1193 fprintf(xCmd,"M %s %s %s\n", zGitMode, zMark, zFNQuoted);
1194 fossil_free(zFNQuoted);
1195 }
1196 db_finalize(&q);
1197
1198 /* Include Fossil-generated auxiliary files in the check-in */
@@ -1224,11 +1237,11 @@
1237 double rEnd; /* time of most recent export */
1238 int rc; /* Result code */
1239 int bForce; /* Do the export and sync even if no changes*/
1240 int fManifest; /* Current "manifest" setting */
1241 FILE *xCmd; /* Pipe to the "git fast-import" command */
1242 FILE *pMarks; /* Git mark files */
1243 Stmt q; /* Queries */
1244 char zLine[200]; /* One line of a mark file */
1245
1246 zDebug = find_option("debug",0,1);
1247 db_find_and_open_repository(0, 0);
@@ -1334,12 +1347,11 @@
1347 xCmd = fopen(zDebug, "wb");
1348 if( xCmd==0 ) fossil_fatal("cannot open file \"%s\" for writing", zDebug);
1349 }
1350 }else{
1351 zCmd = mprintf("git fast-import"
1352 " --export-marks=.mirror_state/marks.txt"
 
1353 " --quiet --done");
1354 gitmirror_message(VERB_NORMAL, "%s\n", zCmd);
1355 xCmd = popen(zCmd, "w");
1356 if( zCmd==0 ){
1357 fossil_fatal("cannot start the \"git fast-import\" command");
@@ -1388,18 +1400,14 @@
1400 nTotal-nLimit, zMirror);
1401
1402 /* Read the export-marks file. Transfer the new marks over into
1403 ** the import-marks file.
1404 */
1405 pMarks = fopen(".mirror_state/marks.txt", "rb");
1406 if( pMarks ){
 
 
 
 
1407 db_prepare(&q, "UPDATE mirror.mmark SET githash=:githash WHERE id=:id");
1408 while( fgets(zLine, sizeof(zLine), pMarks) ){
1409 int j, k;
1410 if( zLine[0]!=':' ) continue;
1411 db_bind_int(&q, ":id", atoi(zLine+1));
1412 for(j=1; zLine[j] && zLine[j]!=' '; j++){}
1413 if( zLine[j]!=' ' ) continue;
@@ -1408,17 +1416,14 @@
1416 for(k=j; fossil_isalnum(zLine[k]); k++){}
1417 zLine[k] = 0;
1418 db_bind_text(&q, ":githash", &zLine[j]);
1419 db_step(&q);
1420 db_reset(&q);
 
 
1421 }
1422 db_finalize(&q);
1423 fclose(pMarks);
1424 file_delete(".mirror_state/marks.txt");
 
1425 }else{
1426 fossil_fatal("git fast-import didn't generate a marks file!");
1427 }
1428 db_multi_exec(
1429 "CREATE INDEX IF NOT EXISTS mirror.mmarkx1 ON mmark(githash);"
1430

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button