Fossil SCM

Rename "fossil mirror" to "fossil git export". Deprecate the "fossil export" command.

drh 2019-03-15 16:38 mirror-cmd
Commit 2faec6b7481520a0b57ea315e6a80462506c539223c983a8487bbfda55935845
1 file changed +86 -65
+86 -65
--- src/export.c
+++ src/export.c
@@ -447,13 +447,13 @@
447447
}while( (rid = bag_next(vers, rid))!=0 );
448448
}
449449
}
450450
}
451451
452
-/*
453
-** COMMAND: export
454
-**
452
+/* This is the original header command (and hence documentation) for
453
+** the "fossil export" command:
454
+**
455455
** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
456456
**
457457
** Write an export of all check-ins to standard output. The export is
458458
** written in the git-fast-export file format assuming the --git option is
459459
** provided. The git-fast-export format is currently the only VCS
@@ -478,10 +478,15 @@
478478
** --rename-trunk NAME use NAME as name of exported trunk branch
479479
** --repository|-R REPOSITORY export the given REPOSITORY
480480
**
481481
** See also: import
482482
*/
483
+/*
484
+** COMMAND: export*
485
+**
486
+** This command is deprecated. Use "fossil git export" instead.
487
+*/
483488
void export_cmd(void){
484489
Stmt q, q2, q3;
485490
Bag blobs, vers;
486491
unsigned int unused_mark = 1;
487492
const char *markfile_in;
@@ -833,20 +838,20 @@
833838
n = topological_sort_checkins(1);
834839
fossil_print("%d reorderings required\n", n);
835840
}
836841
837842
/***************************************************************************
838
-** Implementation of the "fossil mirror" command follows. We hope that the
839
-** new code that follows will largely replace the legacy "fossil export" code
840
-** above.
843
+** Implementation of the "fossil git" command follows. We hope that the
844
+** new code that follows will largely replace the legacy "fossil export"
845
+** and "fossil import" code above.
841846
*/
842847
843848
/*
844849
** Convert characters of z[] that are not allowed to be in branch or
845850
** tag names into "_".
846851
*/
847
-static void mirror_sanitize_git_name(char *z){
852
+static void gitmirror_sanitize_name(char *z){
848853
static unsigned char aSafe[] = {
849854
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
850855
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
851856
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
852857
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 2x */
@@ -875,11 +880,11 @@
875880
** If quoting is not necessary, just return a copy of the input string.
876881
**
877882
** The return value is a held in memory obtained from fossil_malloc()
878883
** and must be freed by the caller.
879884
*/
880
-static char *mirror_quote_filename_if_needed(const char *zIn){
885
+static char *gitmirror_quote_filename_if_needed(const char *zIn){
881886
int i, j;
882887
char c;
883888
int nSpecial = 0;
884889
char *zOut;
885890
for(i=0; (c = zIn[i])!=0; i++){
@@ -915,11 +920,11 @@
915920
**
916921
** The Git tag mechanism is very limited compared to Fossil. Many Fossil
917922
** tags cannot be exported to Git. If this tag cannot be exported, then
918923
** silently ignore it.
919924
*/
920
-static void mirror_send_tag(FILE *xCmd, int rid){
925
+static void gitmirror_send_tag(FILE *xCmd, int rid){
921926
return;
922927
}
923928
924929
/*
925930
** Locate the mark for a UUID.
@@ -926,11 +931,11 @@
926931
**
927932
** If the mark does not exist and if the bCreate flag is false, then
928933
** return 0. If the mark does not exist and the bCreate flag is true,
929934
** then create the mark.
930935
*/
931
-static int mirror_find_mark(const char *zUuid, int bCreate){
936
+static int gitmirror_find_mark(const char *zUuid, int bCreate){
932937
int iMark;
933938
static Stmt sFind, sIns;
934939
db_static_prepare(&sFind,
935940
"SELECT id FROM mirror.mmark WHERE uuid=:uuid"
936941
);
@@ -956,11 +961,11 @@
956961
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
957962
958963
/*
959964
** Export a single file named by zUuid.
960965
*/
961
-static void mirror_send_file(FILE *xCmd, const char *zUuid){
966
+static void gitmirror_send_file(FILE *xCmd, const char *zUuid){
962967
int iMark;
963968
int rid;
964969
int rc;
965970
Blob data;
966971
rid = fast_uuid_to_rid(zUuid);
@@ -971,11 +976,11 @@
971976
if( rc==0 ){
972977
blob_init(&data, 0, 0);
973978
zUuid = zEmptySha3;
974979
}
975980
}
976
- iMark = mirror_find_mark(zUuid, 1);
981
+ iMark = gitmirror_find_mark(zUuid, 1);
977982
fprintf(xCmd, "blob\nmark :%d\ndata %d\n", iMark, blob_size(&data));
978983
fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
979984
fprintf(xCmd, "\n");
980985
blob_reset(&data);
981986
}
@@ -991,11 +996,11 @@
991996
** Before sending the check-in, first make sure all associated files
992997
** have already been exported, and send "blob" records for any that
993998
** have not been. Update the MIRROR.MMARK table so that it holds the
994999
** marks for the exported files.
9951000
*/
996
-static void mirror_send_checkin(
1001
+static void gitmirror_send_checkin(
9971002
FILE *xCmd, /* Write fast-import text on this pipe */
9981003
int rid, /* BLOB.RID for the check-in to export */
9991004
const char *zUuid, /* BLOB.UUID for the check-in to export */
10001005
int *pnLimit, /* Stop when the counter reaches zero */
10011006
int fManifest /* MFESTFLG_* values */
@@ -1017,15 +1022,15 @@
10171022
}
10181023
10191024
/* Check to see if any parent logins have not yet been processed, and
10201025
** if so, create them */
10211026
for(i=0; i<pMan->nParent; i++){
1022
- int iMark = mirror_find_mark(pMan->azParent[i], 0);
1027
+ int iMark = gitmirror_find_mark(pMan->azParent[i], 0);
10231028
if( iMark<=0 ){
10241029
int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
10251030
pMan->azParent[i]);
1026
- mirror_send_checkin(xCmd, prid, pMan->azParent[i], pnLimit, fManifest);
1031
+ gitmirror_send_checkin(xCmd, prid, pMan->azParent[i], pnLimit, fManifest);
10271032
if( *pnLimit<=0 ){
10281033
manifest_destroy(pMan);
10291034
return;
10301035
}
10311036
}
@@ -1037,11 +1042,11 @@
10371042
" WHERE uuid NOT IN (SELECT uuid FROM mirror.mmark)",
10381043
zUuid
10391044
);
10401045
while( db_step(&q)==SQLITE_ROW ){
10411046
const char *zFUuid = db_column_text(&q, 0);
1042
- mirror_send_file(xCmd, zFUuid);
1047
+ gitmirror_send_file(xCmd, zFUuid);
10431048
}
10441049
db_finalize(&q);
10451050
10461051
/* Figure out which branch this check-in is a member of */
10471052
zBranch = db_text(0,
@@ -1052,17 +1057,17 @@
10521057
fossil_free(zBranch);
10531058
zBranch = mprintf("master");
10541059
}else if( zBranch==0 ){
10551060
zBranch = mprintf("unknown");
10561061
}else{
1057
- mirror_sanitize_git_name(zBranch);
1062
+ gitmirror_sanitize_name(zBranch);
10581063
}
10591064
10601065
/* Export the check-in */
10611066
fprintf(xCmd, "commit refs/heads/%s\n", zBranch);
10621067
fossil_free(zBranch);
1063
- iMark = mirror_find_mark(zUuid, 1);
1068
+ iMark = gitmirror_find_mark(zUuid, 1);
10641069
fprintf(xCmd, "mark :%d\n", iMark);
10651070
fprintf(xCmd, "committer %s <%[email protected]> %lld +0000\n",
10661071
pMan->zUser, pMan->zUser,
10671072
(sqlite3_int64)((pMan->rDate-2440587.5)*86400.0)
10681073
);
@@ -1069,11 +1074,11 @@
10691074
zCom = pMan->zComment;
10701075
if( zCom==0 ) zCom = "(no comment)";
10711076
fprintf(xCmd, "data %d\n%s\n", (int)strlen(zCom), zCom);
10721077
iParent = -1; /* Which ancestor is the primary parent */
10731078
for(i=0; i<pMan->nParent; i++){
1074
- int iOther = mirror_find_mark(pMan->azParent[i], 0);
1079
+ int iOther = gitmirror_find_mark(pMan->azParent[i], 0);
10751080
if( iOther==0 ) continue;
10761081
if( iParent<0 ){
10771082
iParent = i;
10781083
fprintf(xCmd, "from :%d\n", iOther);
10791084
}else{
@@ -1115,11 +1120,11 @@
11151120
char *zFNQuoted = 0;
11161121
if( zMode ){
11171122
if( strchr(zMode,'x') ) zGitMode = "100755";
11181123
if( strchr(zMode,'l') ) zGitMode = "120000";
11191124
}
1120
- zFNQuoted = mirror_quote_filename_if_needed(zFilename);
1125
+ zFNQuoted = gitmirror_quote_filename_if_needed(zFilename);
11211126
fprintf(xCmd,"M %s :%d %s\n", zGitMode, iMark, zFNQuoted);
11221127
fossil_free(zFNQuoted);
11231128
}
11241129
db_finalize(&q);
11251130
@@ -1147,51 +1152,13 @@
11471152
/* The check-in is finished, so decrement the counter */
11481153
(*pnLimit)--;
11491154
}
11501155
11511156
/*
1152
-** COMMAND: mirror
1153
-**
1154
-** Usage: %fossil mirror [--git] MIRROR [-R FOSSIL-REPO]
1155
-**
1156
-** Create or update another type of repository that is is mirror of
1157
-** a Fossil repository.
1158
-**
1159
-** The current implementation only supports mirrors to Git, and so
1160
-** the --git option is optional. The ability to mirror to other version
1161
-** control systems may be added in the future, in which case an argument
1162
-** to specify the target version control system will become required.
1163
-**
1164
-** The MIRROR argument is the name of the secondary repository. In the
1165
-** case of Git, it is the directory that houses the Git repository.
1166
-** If MIRROR does not previously exist, it is created and initialized to
1167
-** a copy of the Fossil repository. If MIRROR does already exist, it is
1168
-** updated with new check-ins that have been added to the Fossil repository
1169
-** since the last "fossil mirror" command to that particular repository.
1170
-**
1171
-** Implementation notes:
1172
-**
1173
-** * The git version control system must be installed in order for
1174
-** this command to work. Fossil will invoke various git commands
1175
-** to run as subprocesses.
1176
-**
1177
-** * Fossil creates a directory named ".mirror_state" in the top level of
1178
-** the created git repository and stores state information in that
1179
-** directory. Do not attempt to manage any files in that directory.
1180
-** Do not change or delete any files in that directory. Doing so
1181
-** may disrupt future calls to the "fossil mirror" command for the
1182
-** mirror repository.
1183
-**
1184
-** Options:
1185
-**
1186
-** --debug FILE Write fast-export text to FILE rather than
1187
-** piping it into "git fast-import".
1188
-**
1189
-** --limit N Add no more than N new check-ins to MIRROR.
1190
-** Useful for debugging
1157
+** Implementation of the "fossil git export" command.
11911158
*/
1192
-void mirror_command(void){
1159
+void gitmirror_export_command(void){
11931160
const char *zLimit; /* Text of the --limit flag */
11941161
int nLimit = 0x7fffffff; /* Numeric value of the --limit flag */
11951162
int nTotal = 0; /* Total number of check-ins to export */
11961163
char *zMirror; /* Name of the mirror */
11971164
char *z; /* Generic string */
@@ -1203,21 +1170,20 @@
12031170
FILE *xCmd; /* Pipe to the "git fast-import" command */
12041171
FILE *pIn, *pOut; /* Git mark files */
12051172
Stmt q; /* Queries */
12061173
char zLine[200]; /* One line of a mark file */
12071174
1208
- find_option("git", 0, 0); /* Ignore the --git option for now */
12091175
zDebug = find_option("debug",0,1);
12101176
db_find_and_open_repository(0, 0);
12111177
zLimit = find_option("limit", 0, 1);
12121178
if( zLimit ){
12131179
nLimit = (unsigned int)atoi(zLimit);
12141180
if( nLimit<=0 ) fossil_fatal("--limit must be positive");
12151181
}
12161182
verify_all_options();
1217
- if( g.argc!=3 ){ usage("--git MIRROR"); }
1218
- zMirror = g.argv[2];
1183
+ if( g.argc!=4 ){ usage("export MIRROR"); }
1184
+ zMirror = g.argv[3];
12191185
12201186
/* Make sure the GIT repository directory exists */
12211187
rc = file_mkdir(zMirror, ExtFILE, 0);
12221188
if( rc ) fossil_fatal("cannot create directory \"%s\"", zMirror);
12231189
@@ -1321,13 +1287,13 @@
13211287
const char *zType = db_column_text(&q, 1);
13221288
int rid = db_column_int(&q, 0);
13231289
const char *zUuid = db_column_text(&q, 3);
13241290
if( rMTime>rEnd ) rEnd = rMTime;
13251291
if( zType[0]=='t' ){
1326
- mirror_send_tag(xCmd, rid);
1292
+ gitmirror_send_tag(xCmd, rid);
13271293
}else{
1328
- mirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest);
1294
+ gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest);
13291295
printf("\r%d/%d ", nTotal-nLimit, nTotal);
13301296
fflush(stdout);
13311297
}
13321298
}
13331299
db_finalize(&q);
@@ -1362,5 +1328,60 @@
13621328
fossil_fatal("git fast-import didn't generate a marks file!");
13631329
}
13641330
13651331
/* Optionally do a "git push" */
13661332
}
1333
+
1334
+/*
1335
+** COMMAND: git
1336
+**
1337
+** Usage: %fossil git SUBCOMMAND
1338
+**
1339
+** Do incremental import or export operations between Fossil and Git.
1340
+** Subcommands:
1341
+**
1342
+** fossil git export MIRROR [OPTIONS]
1343
+**
1344
+** Write content from the Fossil repository into the Git repository
1345
+** in directory MIRROR. The Git repository is created if it does not
1346
+** already exist. If the Git repository does already exist, then
1347
+** new content added to fossil since the previous export is appended.
1348
+**
1349
+** Repeat this command whenever new checkins are added to the Fossil
1350
+** repository in order to reflect those changes into the mirror.
1351
+**
1352
+** The MIRROR directory will contain a subdirectory named
1353
+** ".mirror_state" that contains information that Fossil needs to
1354
+** do incremental exports. Do not attempt to manage or edit the files
1355
+** in that directory since doing so can disrupt future incremental
1356
+** exports.
1357
+**
1358
+** Options:
1359
+** --debug FILE Write fast-export text to FILE rather than
1360
+** piping it into "git fast-import".
1361
+** --limit N Add no more than N new check-ins to MIRROR.
1362
+** Useful for debugging
1363
+**
1364
+** fossil git import MIRROR
1365
+**
1366
+** TBD...
1367
+*/
1368
+void gitmirror_command(void){
1369
+ char *zCmd;
1370
+ int nCmd;
1371
+ if( g.argc<3 ){
1372
+ usage("export ARGS...");
1373
+ }
1374
+ zCmd = g.argv[2];
1375
+ nCmd = (int)strlen(zCmd);
1376
+ if( nCmd>2 && strncmp(zCmd,"export",nCmd)==0 ){
1377
+ gitmirror_export_command();
1378
+ }else
1379
+ if( nCmd>2 && strncmp(zCmd,"import",nCmd)==0 ){
1380
+ fossil_fatal("not yet implemented - check back later");
1381
+ }else
1382
+ {
1383
+ fossil_fatal("unknown subcommand \"%s\": should be one of "
1384
+ "\"export\", \"import\"",
1385
+ zCmd);
1386
+ }
1387
+}
13671388
--- src/export.c
+++ src/export.c
@@ -447,13 +447,13 @@
447 }while( (rid = bag_next(vers, rid))!=0 );
448 }
449 }
450 }
451
452 /*
453 ** COMMAND: export
454 **
455 ** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
456 **
457 ** Write an export of all check-ins to standard output. The export is
458 ** written in the git-fast-export file format assuming the --git option is
459 ** provided. The git-fast-export format is currently the only VCS
@@ -478,10 +478,15 @@
478 ** --rename-trunk NAME use NAME as name of exported trunk branch
479 ** --repository|-R REPOSITORY export the given REPOSITORY
480 **
481 ** See also: import
482 */
 
 
 
 
 
483 void export_cmd(void){
484 Stmt q, q2, q3;
485 Bag blobs, vers;
486 unsigned int unused_mark = 1;
487 const char *markfile_in;
@@ -833,20 +838,20 @@
833 n = topological_sort_checkins(1);
834 fossil_print("%d reorderings required\n", n);
835 }
836
837 /***************************************************************************
838 ** Implementation of the "fossil mirror" command follows. We hope that the
839 ** new code that follows will largely replace the legacy "fossil export" code
840 ** above.
841 */
842
843 /*
844 ** Convert characters of z[] that are not allowed to be in branch or
845 ** tag names into "_".
846 */
847 static void mirror_sanitize_git_name(char *z){
848 static unsigned char aSafe[] = {
849 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
850 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
851 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
852 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 2x */
@@ -875,11 +880,11 @@
875 ** If quoting is not necessary, just return a copy of the input string.
876 **
877 ** The return value is a held in memory obtained from fossil_malloc()
878 ** and must be freed by the caller.
879 */
880 static char *mirror_quote_filename_if_needed(const char *zIn){
881 int i, j;
882 char c;
883 int nSpecial = 0;
884 char *zOut;
885 for(i=0; (c = zIn[i])!=0; i++){
@@ -915,11 +920,11 @@
915 **
916 ** The Git tag mechanism is very limited compared to Fossil. Many Fossil
917 ** tags cannot be exported to Git. If this tag cannot be exported, then
918 ** silently ignore it.
919 */
920 static void mirror_send_tag(FILE *xCmd, int rid){
921 return;
922 }
923
924 /*
925 ** Locate the mark for a UUID.
@@ -926,11 +931,11 @@
926 **
927 ** If the mark does not exist and if the bCreate flag is false, then
928 ** return 0. If the mark does not exist and the bCreate flag is true,
929 ** then create the mark.
930 */
931 static int mirror_find_mark(const char *zUuid, int bCreate){
932 int iMark;
933 static Stmt sFind, sIns;
934 db_static_prepare(&sFind,
935 "SELECT id FROM mirror.mmark WHERE uuid=:uuid"
936 );
@@ -956,11 +961,11 @@
956 "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
957
958 /*
959 ** Export a single file named by zUuid.
960 */
961 static void mirror_send_file(FILE *xCmd, const char *zUuid){
962 int iMark;
963 int rid;
964 int rc;
965 Blob data;
966 rid = fast_uuid_to_rid(zUuid);
@@ -971,11 +976,11 @@
971 if( rc==0 ){
972 blob_init(&data, 0, 0);
973 zUuid = zEmptySha3;
974 }
975 }
976 iMark = mirror_find_mark(zUuid, 1);
977 fprintf(xCmd, "blob\nmark :%d\ndata %d\n", iMark, blob_size(&data));
978 fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
979 fprintf(xCmd, "\n");
980 blob_reset(&data);
981 }
@@ -991,11 +996,11 @@
991 ** Before sending the check-in, first make sure all associated files
992 ** have already been exported, and send "blob" records for any that
993 ** have not been. Update the MIRROR.MMARK table so that it holds the
994 ** marks for the exported files.
995 */
996 static void mirror_send_checkin(
997 FILE *xCmd, /* Write fast-import text on this pipe */
998 int rid, /* BLOB.RID for the check-in to export */
999 const char *zUuid, /* BLOB.UUID for the check-in to export */
1000 int *pnLimit, /* Stop when the counter reaches zero */
1001 int fManifest /* MFESTFLG_* values */
@@ -1017,15 +1022,15 @@
1017 }
1018
1019 /* Check to see if any parent logins have not yet been processed, and
1020 ** if so, create them */
1021 for(i=0; i<pMan->nParent; i++){
1022 int iMark = mirror_find_mark(pMan->azParent[i], 0);
1023 if( iMark<=0 ){
1024 int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
1025 pMan->azParent[i]);
1026 mirror_send_checkin(xCmd, prid, pMan->azParent[i], pnLimit, fManifest);
1027 if( *pnLimit<=0 ){
1028 manifest_destroy(pMan);
1029 return;
1030 }
1031 }
@@ -1037,11 +1042,11 @@
1037 " WHERE uuid NOT IN (SELECT uuid FROM mirror.mmark)",
1038 zUuid
1039 );
1040 while( db_step(&q)==SQLITE_ROW ){
1041 const char *zFUuid = db_column_text(&q, 0);
1042 mirror_send_file(xCmd, zFUuid);
1043 }
1044 db_finalize(&q);
1045
1046 /* Figure out which branch this check-in is a member of */
1047 zBranch = db_text(0,
@@ -1052,17 +1057,17 @@
1052 fossil_free(zBranch);
1053 zBranch = mprintf("master");
1054 }else if( zBranch==0 ){
1055 zBranch = mprintf("unknown");
1056 }else{
1057 mirror_sanitize_git_name(zBranch);
1058 }
1059
1060 /* Export the check-in */
1061 fprintf(xCmd, "commit refs/heads/%s\n", zBranch);
1062 fossil_free(zBranch);
1063 iMark = mirror_find_mark(zUuid, 1);
1064 fprintf(xCmd, "mark :%d\n", iMark);
1065 fprintf(xCmd, "committer %s <%[email protected]> %lld +0000\n",
1066 pMan->zUser, pMan->zUser,
1067 (sqlite3_int64)((pMan->rDate-2440587.5)*86400.0)
1068 );
@@ -1069,11 +1074,11 @@
1069 zCom = pMan->zComment;
1070 if( zCom==0 ) zCom = "(no comment)";
1071 fprintf(xCmd, "data %d\n%s\n", (int)strlen(zCom), zCom);
1072 iParent = -1; /* Which ancestor is the primary parent */
1073 for(i=0; i<pMan->nParent; i++){
1074 int iOther = mirror_find_mark(pMan->azParent[i], 0);
1075 if( iOther==0 ) continue;
1076 if( iParent<0 ){
1077 iParent = i;
1078 fprintf(xCmd, "from :%d\n", iOther);
1079 }else{
@@ -1115,11 +1120,11 @@
1115 char *zFNQuoted = 0;
1116 if( zMode ){
1117 if( strchr(zMode,'x') ) zGitMode = "100755";
1118 if( strchr(zMode,'l') ) zGitMode = "120000";
1119 }
1120 zFNQuoted = mirror_quote_filename_if_needed(zFilename);
1121 fprintf(xCmd,"M %s :%d %s\n", zGitMode, iMark, zFNQuoted);
1122 fossil_free(zFNQuoted);
1123 }
1124 db_finalize(&q);
1125
@@ -1147,51 +1152,13 @@
1147 /* The check-in is finished, so decrement the counter */
1148 (*pnLimit)--;
1149 }
1150
1151 /*
1152 ** COMMAND: mirror
1153 **
1154 ** Usage: %fossil mirror [--git] MIRROR [-R FOSSIL-REPO]
1155 **
1156 ** Create or update another type of repository that is is mirror of
1157 ** a Fossil repository.
1158 **
1159 ** The current implementation only supports mirrors to Git, and so
1160 ** the --git option is optional. The ability to mirror to other version
1161 ** control systems may be added in the future, in which case an argument
1162 ** to specify the target version control system will become required.
1163 **
1164 ** The MIRROR argument is the name of the secondary repository. In the
1165 ** case of Git, it is the directory that houses the Git repository.
1166 ** If MIRROR does not previously exist, it is created and initialized to
1167 ** a copy of the Fossil repository. If MIRROR does already exist, it is
1168 ** updated with new check-ins that have been added to the Fossil repository
1169 ** since the last "fossil mirror" command to that particular repository.
1170 **
1171 ** Implementation notes:
1172 **
1173 ** * The git version control system must be installed in order for
1174 ** this command to work. Fossil will invoke various git commands
1175 ** to run as subprocesses.
1176 **
1177 ** * Fossil creates a directory named ".mirror_state" in the top level of
1178 ** the created git repository and stores state information in that
1179 ** directory. Do not attempt to manage any files in that directory.
1180 ** Do not change or delete any files in that directory. Doing so
1181 ** may disrupt future calls to the "fossil mirror" command for the
1182 ** mirror repository.
1183 **
1184 ** Options:
1185 **
1186 ** --debug FILE Write fast-export text to FILE rather than
1187 ** piping it into "git fast-import".
1188 **
1189 ** --limit N Add no more than N new check-ins to MIRROR.
1190 ** Useful for debugging
1191 */
1192 void mirror_command(void){
1193 const char *zLimit; /* Text of the --limit flag */
1194 int nLimit = 0x7fffffff; /* Numeric value of the --limit flag */
1195 int nTotal = 0; /* Total number of check-ins to export */
1196 char *zMirror; /* Name of the mirror */
1197 char *z; /* Generic string */
@@ -1203,21 +1170,20 @@
1203 FILE *xCmd; /* Pipe to the "git fast-import" command */
1204 FILE *pIn, *pOut; /* Git mark files */
1205 Stmt q; /* Queries */
1206 char zLine[200]; /* One line of a mark file */
1207
1208 find_option("git", 0, 0); /* Ignore the --git option for now */
1209 zDebug = find_option("debug",0,1);
1210 db_find_and_open_repository(0, 0);
1211 zLimit = find_option("limit", 0, 1);
1212 if( zLimit ){
1213 nLimit = (unsigned int)atoi(zLimit);
1214 if( nLimit<=0 ) fossil_fatal("--limit must be positive");
1215 }
1216 verify_all_options();
1217 if( g.argc!=3 ){ usage("--git MIRROR"); }
1218 zMirror = g.argv[2];
1219
1220 /* Make sure the GIT repository directory exists */
1221 rc = file_mkdir(zMirror, ExtFILE, 0);
1222 if( rc ) fossil_fatal("cannot create directory \"%s\"", zMirror);
1223
@@ -1321,13 +1287,13 @@
1321 const char *zType = db_column_text(&q, 1);
1322 int rid = db_column_int(&q, 0);
1323 const char *zUuid = db_column_text(&q, 3);
1324 if( rMTime>rEnd ) rEnd = rMTime;
1325 if( zType[0]=='t' ){
1326 mirror_send_tag(xCmd, rid);
1327 }else{
1328 mirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest);
1329 printf("\r%d/%d ", nTotal-nLimit, nTotal);
1330 fflush(stdout);
1331 }
1332 }
1333 db_finalize(&q);
@@ -1362,5 +1328,60 @@
1362 fossil_fatal("git fast-import didn't generate a marks file!");
1363 }
1364
1365 /* Optionally do a "git push" */
1366 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1367
--- src/export.c
+++ src/export.c
@@ -447,13 +447,13 @@
447 }while( (rid = bag_next(vers, rid))!=0 );
448 }
449 }
450 }
451
452 /* This is the original header command (and hence documentation) for
453 ** the "fossil export" command:
454 **
455 ** Usage: %fossil export --git ?OPTIONS? ?REPOSITORY?
456 **
457 ** Write an export of all check-ins to standard output. The export is
458 ** written in the git-fast-export file format assuming the --git option is
459 ** provided. The git-fast-export format is currently the only VCS
@@ -478,10 +478,15 @@
478 ** --rename-trunk NAME use NAME as name of exported trunk branch
479 ** --repository|-R REPOSITORY export the given REPOSITORY
480 **
481 ** See also: import
482 */
483 /*
484 ** COMMAND: export*
485 **
486 ** This command is deprecated. Use "fossil git export" instead.
487 */
488 void export_cmd(void){
489 Stmt q, q2, q3;
490 Bag blobs, vers;
491 unsigned int unused_mark = 1;
492 const char *markfile_in;
@@ -833,20 +838,20 @@
838 n = topological_sort_checkins(1);
839 fossil_print("%d reorderings required\n", n);
840 }
841
842 /***************************************************************************
843 ** Implementation of the "fossil git" command follows. We hope that the
844 ** new code that follows will largely replace the legacy "fossil export"
845 ** and "fossil import" code above.
846 */
847
848 /*
849 ** Convert characters of z[] that are not allowed to be in branch or
850 ** tag names into "_".
851 */
852 static void gitmirror_sanitize_name(char *z){
853 static unsigned char aSafe[] = {
854 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
855 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
856 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
857 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 2x */
@@ -875,11 +880,11 @@
880 ** If quoting is not necessary, just return a copy of the input string.
881 **
882 ** The return value is a held in memory obtained from fossil_malloc()
883 ** and must be freed by the caller.
884 */
885 static char *gitmirror_quote_filename_if_needed(const char *zIn){
886 int i, j;
887 char c;
888 int nSpecial = 0;
889 char *zOut;
890 for(i=0; (c = zIn[i])!=0; i++){
@@ -915,11 +920,11 @@
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.
@@ -926,11 +931,11 @@
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,
934 ** then create the mark.
935 */
936 static int gitmirror_find_mark(const char *zUuid, int bCreate){
937 int iMark;
938 static Stmt sFind, sIns;
939 db_static_prepare(&sFind,
940 "SELECT id FROM mirror.mmark WHERE uuid=:uuid"
941 );
@@ -956,11 +961,11 @@
961 "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
962
963 /*
964 ** Export a single file named by zUuid.
965 */
966 static void gitmirror_send_file(FILE *xCmd, const char *zUuid){
967 int iMark;
968 int rid;
969 int rc;
970 Blob data;
971 rid = fast_uuid_to_rid(zUuid);
@@ -971,11 +976,11 @@
976 if( rc==0 ){
977 blob_init(&data, 0, 0);
978 zUuid = zEmptySha3;
979 }
980 }
981 iMark = gitmirror_find_mark(zUuid, 1);
982 fprintf(xCmd, "blob\nmark :%d\ndata %d\n", iMark, blob_size(&data));
983 fwrite(blob_buffer(&data), 1, blob_size(&data), xCmd);
984 fprintf(xCmd, "\n");
985 blob_reset(&data);
986 }
@@ -991,11 +996,11 @@
996 ** Before sending the check-in, first make sure all associated files
997 ** have already been exported, and send "blob" records for any that
998 ** have not been. Update the MIRROR.MMARK table so that it holds the
999 ** marks for the exported files.
1000 */
1001 static void gitmirror_send_checkin(
1002 FILE *xCmd, /* Write fast-import text on this pipe */
1003 int rid, /* BLOB.RID for the check-in to export */
1004 const char *zUuid, /* BLOB.UUID for the check-in to export */
1005 int *pnLimit, /* Stop when the counter reaches zero */
1006 int fManifest /* MFESTFLG_* values */
@@ -1017,15 +1022,15 @@
1022 }
1023
1024 /* Check to see if any parent logins have not yet been processed, and
1025 ** if so, create them */
1026 for(i=0; i<pMan->nParent; i++){
1027 int iMark = gitmirror_find_mark(pMan->azParent[i], 0);
1028 if( iMark<=0 ){
1029 int prid = db_int(0, "SELECT rid FROM blob WHERE uuid=%Q",
1030 pMan->azParent[i]);
1031 gitmirror_send_checkin(xCmd, prid, pMan->azParent[i], pnLimit, fManifest);
1032 if( *pnLimit<=0 ){
1033 manifest_destroy(pMan);
1034 return;
1035 }
1036 }
@@ -1037,11 +1042,11 @@
1042 " WHERE uuid NOT IN (SELECT uuid FROM mirror.mmark)",
1043 zUuid
1044 );
1045 while( db_step(&q)==SQLITE_ROW ){
1046 const char *zFUuid = db_column_text(&q, 0);
1047 gitmirror_send_file(xCmd, zFUuid);
1048 }
1049 db_finalize(&q);
1050
1051 /* Figure out which branch this check-in is a member of */
1052 zBranch = db_text(0,
@@ -1052,17 +1057,17 @@
1057 fossil_free(zBranch);
1058 zBranch = mprintf("master");
1059 }else if( zBranch==0 ){
1060 zBranch = mprintf("unknown");
1061 }else{
1062 gitmirror_sanitize_name(zBranch);
1063 }
1064
1065 /* Export the check-in */
1066 fprintf(xCmd, "commit refs/heads/%s\n", zBranch);
1067 fossil_free(zBranch);
1068 iMark = gitmirror_find_mark(zUuid, 1);
1069 fprintf(xCmd, "mark :%d\n", iMark);
1070 fprintf(xCmd, "committer %s <%[email protected]> %lld +0000\n",
1071 pMan->zUser, pMan->zUser,
1072 (sqlite3_int64)((pMan->rDate-2440587.5)*86400.0)
1073 );
@@ -1069,11 +1074,11 @@
1074 zCom = pMan->zComment;
1075 if( zCom==0 ) zCom = "(no comment)";
1076 fprintf(xCmd, "data %d\n%s\n", (int)strlen(zCom), zCom);
1077 iParent = -1; /* Which ancestor is the primary parent */
1078 for(i=0; i<pMan->nParent; i++){
1079 int iOther = gitmirror_find_mark(pMan->azParent[i], 0);
1080 if( iOther==0 ) continue;
1081 if( iParent<0 ){
1082 iParent = i;
1083 fprintf(xCmd, "from :%d\n", iOther);
1084 }else{
@@ -1115,11 +1120,11 @@
1120 char *zFNQuoted = 0;
1121 if( zMode ){
1122 if( strchr(zMode,'x') ) zGitMode = "100755";
1123 if( strchr(zMode,'l') ) zGitMode = "120000";
1124 }
1125 zFNQuoted = gitmirror_quote_filename_if_needed(zFilename);
1126 fprintf(xCmd,"M %s :%d %s\n", zGitMode, iMark, zFNQuoted);
1127 fossil_free(zFNQuoted);
1128 }
1129 db_finalize(&q);
1130
@@ -1147,51 +1152,13 @@
1152 /* The check-in is finished, so decrement the counter */
1153 (*pnLimit)--;
1154 }
1155
1156 /*
1157 ** Implementation of the "fossil git export" command.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1158 */
1159 void gitmirror_export_command(void){
1160 const char *zLimit; /* Text of the --limit flag */
1161 int nLimit = 0x7fffffff; /* Numeric value of the --limit flag */
1162 int nTotal = 0; /* Total number of check-ins to export */
1163 char *zMirror; /* Name of the mirror */
1164 char *z; /* Generic string */
@@ -1203,21 +1170,20 @@
1170 FILE *xCmd; /* Pipe to the "git fast-import" command */
1171 FILE *pIn, *pOut; /* Git mark files */
1172 Stmt q; /* Queries */
1173 char zLine[200]; /* One line of a mark file */
1174
 
1175 zDebug = find_option("debug",0,1);
1176 db_find_and_open_repository(0, 0);
1177 zLimit = find_option("limit", 0, 1);
1178 if( zLimit ){
1179 nLimit = (unsigned int)atoi(zLimit);
1180 if( nLimit<=0 ) fossil_fatal("--limit must be positive");
1181 }
1182 verify_all_options();
1183 if( g.argc!=4 ){ usage("export MIRROR"); }
1184 zMirror = g.argv[3];
1185
1186 /* Make sure the GIT repository directory exists */
1187 rc = file_mkdir(zMirror, ExtFILE, 0);
1188 if( rc ) fossil_fatal("cannot create directory \"%s\"", zMirror);
1189
@@ -1321,13 +1287,13 @@
1287 const char *zType = db_column_text(&q, 1);
1288 int rid = db_column_int(&q, 0);
1289 const char *zUuid = db_column_text(&q, 3);
1290 if( rMTime>rEnd ) rEnd = rMTime;
1291 if( zType[0]=='t' ){
1292 gitmirror_send_tag(xCmd, rid);
1293 }else{
1294 gitmirror_send_checkin(xCmd, rid, zUuid, &nLimit, fManifest);
1295 printf("\r%d/%d ", nTotal-nLimit, nTotal);
1296 fflush(stdout);
1297 }
1298 }
1299 db_finalize(&q);
@@ -1362,5 +1328,60 @@
1328 fossil_fatal("git fast-import didn't generate a marks file!");
1329 }
1330
1331 /* Optionally do a "git push" */
1332 }
1333
1334 /*
1335 ** COMMAND: git
1336 **
1337 ** Usage: %fossil git SUBCOMMAND
1338 **
1339 ** Do incremental import or export operations between Fossil and Git.
1340 ** Subcommands:
1341 **
1342 ** fossil git export MIRROR [OPTIONS]
1343 **
1344 ** Write content from the Fossil repository into the Git repository
1345 ** in directory MIRROR. The Git repository is created if it does not
1346 ** already exist. If the Git repository does already exist, then
1347 ** new content added to fossil since the previous export is appended.
1348 **
1349 ** Repeat this command whenever new checkins are added to the Fossil
1350 ** repository in order to reflect those changes into the mirror.
1351 **
1352 ** The MIRROR directory will contain a subdirectory named
1353 ** ".mirror_state" that contains information that Fossil needs to
1354 ** do incremental exports. Do not attempt to manage or edit the files
1355 ** in that directory since doing so can disrupt future incremental
1356 ** exports.
1357 **
1358 ** Options:
1359 ** --debug FILE Write fast-export text to FILE rather than
1360 ** piping it into "git fast-import".
1361 ** --limit N Add no more than N new check-ins to MIRROR.
1362 ** Useful for debugging
1363 **
1364 ** fossil git import MIRROR
1365 **
1366 ** TBD...
1367 */
1368 void gitmirror_command(void){
1369 char *zCmd;
1370 int nCmd;
1371 if( g.argc<3 ){
1372 usage("export ARGS...");
1373 }
1374 zCmd = g.argv[2];
1375 nCmd = (int)strlen(zCmd);
1376 if( nCmd>2 && strncmp(zCmd,"export",nCmd)==0 ){
1377 gitmirror_export_command();
1378 }else
1379 if( nCmd>2 && strncmp(zCmd,"import",nCmd)==0 ){
1380 fossil_fatal("not yet implemented - check back later");
1381 }else
1382 {
1383 fossil_fatal("unknown subcommand \"%s\": should be one of "
1384 "\"export\", \"import\"",
1385 zCmd);
1386 }
1387 }
1388

Keyboard Shortcuts

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