Fossil SCM

Add support for GIT comment tags, as suggested [https://www.mail-archive.com/[email protected]/msg24595.html|here]. Implementation by Roy Marples, but modified to use the (existing) 'T' card in stead of the 'C' card.

jan.nijtmans 2017-04-03 11:40 trunk merge
Commit 3bba2a6e8275c0db2d5c02c2a8f1950f9e4b719127b2b253ae58302e37302202
+87 -20
--- src/export.c
+++ src/export.c
@@ -19,10 +19,17 @@
1919
*/
2020
#include "config.h"
2121
#include "export.h"
2222
#include <assert.h>
2323
24
+/*
25
+** State information common to all export types.
26
+*/
27
+static struct {
28
+ const char *zTrunkName; /* Name of trunk branch */
29
+} gexport;
30
+
2431
#if INTERFACE
2532
/*
2633
** struct mark_t
2734
** holds information for translating between git commits
2835
** and fossil commits.
@@ -161,10 +168,68 @@
161168
printf(" %s <%s>", zName, zEmail);
162169
free(zName);
163170
free(zEmail);
164171
db_reset(&q);
165172
}
173
+
174
+#define REFREPLACEMENT '_'
175
+
176
+/*
177
+** Output a sanitized git named reference.
178
+** https://git-scm.com/docs/git-check-ref-format
179
+** This implementation assumes we are only printing
180
+** the branch or tag part of the reference.
181
+*/
182
+static void print_ref(const char *zRef){
183
+ char *zEncoded = mprintf("%s", zRef);
184
+ int i, w;
185
+ if (zEncoded[0]=='@' && zEncoded[1]=='\0'){
186
+ putchar(REFREPLACEMENT);
187
+ return;
188
+ }
189
+ for(i=0, w=0; zEncoded[i]; i++, w++){
190
+ if( i!=0 ){ /* Two letter tests */
191
+ if( (zEncoded[i-1]=='.' && zEncoded[i]=='.') ||
192
+ (zEncoded[i-1]=='@' && zEncoded[i]=='{') ){
193
+ zEncoded[w]=zEncoded[w-1]=REFREPLACEMENT;
194
+ continue;
195
+ }
196
+ if( zEncoded[i-1]=='/' && zEncoded[i]=='/' ){
197
+ w--; /* Normalise to a single / by rolling back w */
198
+ continue;
199
+ }
200
+ }
201
+ /* No control characters */
202
+ if( (unsigned)zEncoded[i]<0x20 || zEncoded[i]==0x7f ){
203
+ zEncoded[w]=REFREPLACEMENT;
204
+ continue;
205
+ }
206
+ switch( zEncoded[i] ){
207
+ case ' ':
208
+ case '^':
209
+ case ':':
210
+ case '?':
211
+ case '*':
212
+ case '[':
213
+ case '\\':
214
+ zEncoded[w]=REFREPLACEMENT;
215
+ break;
216
+ }
217
+ }
218
+ /* Cannot begin with a . or / */
219
+ if( zEncoded[0]=='.' || zEncoded[0] == '/' ) zEncoded[0]=REFREPLACEMENT;
220
+ if( i>0 ){
221
+ i--; w--;
222
+ /* Or end with a . or / */
223
+ if( zEncoded[i]=='.' || zEncoded[i] == '/' ) zEncoded[w]=REFREPLACEMENT;
224
+ /* Cannot end with .lock */
225
+ if ( i>4 && strcmp((zEncoded+i)-5, ".lock")==0 )
226
+ memset((zEncoded+w)-5, REFREPLACEMENT, 5);
227
+ }
228
+ printf("%s", zEncoded);
229
+ free(zEncoded);
230
+}
166231
167232
#define BLOBMARK(rid) ((rid) * 2)
168233
#define COMMITMARK(rid) ((rid) * 2 + 1)
169234
170235
/*
@@ -413,10 +478,11 @@
413478
** blobs written on exit for use with "--import-marks" on the next run.
414479
**
415480
** Options:
416481
** --export-marks FILE export rids of exported data to FILE
417482
** --import-marks FILE read rids of data to ignore from FILE
483
+** --rename-trunk NAME use NAME as name of exported trunk branch
418484
** --repository|-R REPOSITORY export the given REPOSITORY
419485
**
420486
** See also: import
421487
*/
422488
void export_cmd(void){
@@ -431,10 +497,14 @@
431497
bag_init(&vers);
432498
433499
find_option("git", 0, 0); /* Ignore the --git option for now */
434500
markfile_in = find_option("import-marks", 0, 1);
435501
markfile_out = find_option("export-marks", 0, 1);
502
+
503
+ if( !(gexport.zTrunkName = find_option("rename-trunk", 0, 1)) ){
504
+ gexport.zTrunkName = "trunk";
505
+ }
436506
437507
db_find_and_open_repository(0, 2);
438508
verify_all_options();
439509
if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
440510
@@ -547,26 +617,22 @@
547617
const char *zSecondsSince1970 = db_column_text(&q, 0);
548618
int ckinId = db_column_int(&q, 1);
549619
const char *zComment = db_column_text(&q, 2);
550620
const char *zUser = db_column_text(&q, 3);
551621
const char *zBranch = db_column_text(&q, 4);
552
- char *zBr;
553622
char *zMark;
554623
555624
bag_insert(&vers, ckinId);
556625
db_bind_int(&q2, ":rid", ckinId);
557626
db_step(&q2);
558627
db_reset(&q2);
559
- if( zBranch==0 ) zBranch = "trunk";
560
- zBr = mprintf("%s", zBranch);
561
- for(i=0; zBr[i]; i++){
562
- if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
563
- }
628
+ if( zBranch==0 || fossil_strcmp(zBranch, "trunk")==0 ) zBranch = gexport.zTrunkName;
564629
zMark = mark_name_from_rid(ckinId, &unused_mark);
565
- printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
630
+ printf("commit refs/heads/");
631
+ print_ref(zBranch);
632
+ printf("\nmark %s\n", zMark);
566633
free(zMark);
567
- free(zBr);
568634
printf("committer");
569635
print_person(zUser);
570636
printf(" %s +0000\n", zSecondsSince1970);
571637
if( zComment==0 ) zComment = "null comment";
572638
printf("data %d\n%s\n", (int)strlen(zComment), zComment);
@@ -630,33 +696,34 @@
630696
manifest_cache_clear();
631697
632698
633699
/* Output tags */
634700
db_prepare(&q,
635
- "SELECT tagname, rid, strftime('%%s',mtime)"
701
+ "SELECT tagname, rid, strftime('%%s',mtime),"
702
+ " (SELECT coalesce(euser, user) FROM event WHERE objid=rid),"
703
+ " value"
636704
" FROM tagxref JOIN tag USING(tagid)"
637705
" WHERE tagtype=1 AND tagname GLOB 'sym-*'"
638706
);
639707
while( db_step(&q)==SQLITE_ROW ){
640708
const char *zTagname = db_column_text(&q, 0);
641
- char *zEncoded = 0;
642709
int rid = db_column_int(&q, 1);
643710
char *zMark = mark_name_from_rid(rid, &unused_mark);
644711
const char *zSecSince1970 = db_column_text(&q, 2);
645
- int i;
712
+ const char *zUser = db_column_text(&q, 3);
713
+ const char *zValue = db_column_text(&q, 4);
646714
if( rid==0 || !bag_find(&vers, rid) ) continue;
647715
zTagname += 4;
648
- zEncoded = mprintf("%s", zTagname);
649
- for(i=0; zEncoded[i]; i++){
650
- if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
651
- }
652
- printf("tag %s\n", zEncoded);
653
- printf("from %s\n", zMark);
716
+ printf("tag ");
717
+ print_ref(zTagname);
718
+ printf("\nfrom %s\n", zMark);
654719
free(zMark);
655
- printf("tagger <tagger> %s +0000\n", zSecSince1970);
656
- printf("data 0\n");
657
- fossil_free(zEncoded);
720
+ printf("tagger");
721
+ print_person(zUser);
722
+ printf(" %s +0000\n", zSecSince1970);
723
+ printf("data %d\n", zValue==NULL?0:strlen(zValue)+1);
724
+ if( zValue!=NULL ) printf("%s\n",zValue);
658725
}
659726
db_finalize(&q);
660727
661728
if( markfile_out!=0 ){
662729
FILE *f;
663730
--- src/export.c
+++ src/export.c
@@ -19,10 +19,17 @@
19 */
20 #include "config.h"
21 #include "export.h"
22 #include <assert.h>
23
 
 
 
 
 
 
 
24 #if INTERFACE
25 /*
26 ** struct mark_t
27 ** holds information for translating between git commits
28 ** and fossil commits.
@@ -161,10 +168,68 @@
161 printf(" %s <%s>", zName, zEmail);
162 free(zName);
163 free(zEmail);
164 db_reset(&q);
165 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
167 #define BLOBMARK(rid) ((rid) * 2)
168 #define COMMITMARK(rid) ((rid) * 2 + 1)
169
170 /*
@@ -413,10 +478,11 @@
413 ** blobs written on exit for use with "--import-marks" on the next run.
414 **
415 ** Options:
416 ** --export-marks FILE export rids of exported data to FILE
417 ** --import-marks FILE read rids of data to ignore from FILE
 
418 ** --repository|-R REPOSITORY export the given REPOSITORY
419 **
420 ** See also: import
421 */
422 void export_cmd(void){
@@ -431,10 +497,14 @@
431 bag_init(&vers);
432
433 find_option("git", 0, 0); /* Ignore the --git option for now */
434 markfile_in = find_option("import-marks", 0, 1);
435 markfile_out = find_option("export-marks", 0, 1);
 
 
 
 
436
437 db_find_and_open_repository(0, 2);
438 verify_all_options();
439 if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
440
@@ -547,26 +617,22 @@
547 const char *zSecondsSince1970 = db_column_text(&q, 0);
548 int ckinId = db_column_int(&q, 1);
549 const char *zComment = db_column_text(&q, 2);
550 const char *zUser = db_column_text(&q, 3);
551 const char *zBranch = db_column_text(&q, 4);
552 char *zBr;
553 char *zMark;
554
555 bag_insert(&vers, ckinId);
556 db_bind_int(&q2, ":rid", ckinId);
557 db_step(&q2);
558 db_reset(&q2);
559 if( zBranch==0 ) zBranch = "trunk";
560 zBr = mprintf("%s", zBranch);
561 for(i=0; zBr[i]; i++){
562 if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
563 }
564 zMark = mark_name_from_rid(ckinId, &unused_mark);
565 printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
 
 
566 free(zMark);
567 free(zBr);
568 printf("committer");
569 print_person(zUser);
570 printf(" %s +0000\n", zSecondsSince1970);
571 if( zComment==0 ) zComment = "null comment";
572 printf("data %d\n%s\n", (int)strlen(zComment), zComment);
@@ -630,33 +696,34 @@
630 manifest_cache_clear();
631
632
633 /* Output tags */
634 db_prepare(&q,
635 "SELECT tagname, rid, strftime('%%s',mtime)"
 
 
636 " FROM tagxref JOIN tag USING(tagid)"
637 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
638 );
639 while( db_step(&q)==SQLITE_ROW ){
640 const char *zTagname = db_column_text(&q, 0);
641 char *zEncoded = 0;
642 int rid = db_column_int(&q, 1);
643 char *zMark = mark_name_from_rid(rid, &unused_mark);
644 const char *zSecSince1970 = db_column_text(&q, 2);
645 int i;
 
646 if( rid==0 || !bag_find(&vers, rid) ) continue;
647 zTagname += 4;
648 zEncoded = mprintf("%s", zTagname);
649 for(i=0; zEncoded[i]; i++){
650 if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
651 }
652 printf("tag %s\n", zEncoded);
653 printf("from %s\n", zMark);
654 free(zMark);
655 printf("tagger <tagger> %s +0000\n", zSecSince1970);
656 printf("data 0\n");
657 fossil_free(zEncoded);
 
 
658 }
659 db_finalize(&q);
660
661 if( markfile_out!=0 ){
662 FILE *f;
663
--- src/export.c
+++ src/export.c
@@ -19,10 +19,17 @@
19 */
20 #include "config.h"
21 #include "export.h"
22 #include <assert.h>
23
24 /*
25 ** State information common to all export types.
26 */
27 static struct {
28 const char *zTrunkName; /* Name of trunk branch */
29 } gexport;
30
31 #if INTERFACE
32 /*
33 ** struct mark_t
34 ** holds information for translating between git commits
35 ** and fossil commits.
@@ -161,10 +168,68 @@
168 printf(" %s <%s>", zName, zEmail);
169 free(zName);
170 free(zEmail);
171 db_reset(&q);
172 }
173
174 #define REFREPLACEMENT '_'
175
176 /*
177 ** Output a sanitized git named reference.
178 ** https://git-scm.com/docs/git-check-ref-format
179 ** This implementation assumes we are only printing
180 ** the branch or tag part of the reference.
181 */
182 static void print_ref(const char *zRef){
183 char *zEncoded = mprintf("%s", zRef);
184 int i, w;
185 if (zEncoded[0]=='@' && zEncoded[1]=='\0'){
186 putchar(REFREPLACEMENT);
187 return;
188 }
189 for(i=0, w=0; zEncoded[i]; i++, w++){
190 if( i!=0 ){ /* Two letter tests */
191 if( (zEncoded[i-1]=='.' && zEncoded[i]=='.') ||
192 (zEncoded[i-1]=='@' && zEncoded[i]=='{') ){
193 zEncoded[w]=zEncoded[w-1]=REFREPLACEMENT;
194 continue;
195 }
196 if( zEncoded[i-1]=='/' && zEncoded[i]=='/' ){
197 w--; /* Normalise to a single / by rolling back w */
198 continue;
199 }
200 }
201 /* No control characters */
202 if( (unsigned)zEncoded[i]<0x20 || zEncoded[i]==0x7f ){
203 zEncoded[w]=REFREPLACEMENT;
204 continue;
205 }
206 switch( zEncoded[i] ){
207 case ' ':
208 case '^':
209 case ':':
210 case '?':
211 case '*':
212 case '[':
213 case '\\':
214 zEncoded[w]=REFREPLACEMENT;
215 break;
216 }
217 }
218 /* Cannot begin with a . or / */
219 if( zEncoded[0]=='.' || zEncoded[0] == '/' ) zEncoded[0]=REFREPLACEMENT;
220 if( i>0 ){
221 i--; w--;
222 /* Or end with a . or / */
223 if( zEncoded[i]=='.' || zEncoded[i] == '/' ) zEncoded[w]=REFREPLACEMENT;
224 /* Cannot end with .lock */
225 if ( i>4 && strcmp((zEncoded+i)-5, ".lock")==0 )
226 memset((zEncoded+w)-5, REFREPLACEMENT, 5);
227 }
228 printf("%s", zEncoded);
229 free(zEncoded);
230 }
231
232 #define BLOBMARK(rid) ((rid) * 2)
233 #define COMMITMARK(rid) ((rid) * 2 + 1)
234
235 /*
@@ -413,10 +478,11 @@
478 ** blobs written on exit for use with "--import-marks" on the next run.
479 **
480 ** Options:
481 ** --export-marks FILE export rids of exported data to FILE
482 ** --import-marks FILE read rids of data to ignore from FILE
483 ** --rename-trunk NAME use NAME as name of exported trunk branch
484 ** --repository|-R REPOSITORY export the given REPOSITORY
485 **
486 ** See also: import
487 */
488 void export_cmd(void){
@@ -431,10 +497,14 @@
497 bag_init(&vers);
498
499 find_option("git", 0, 0); /* Ignore the --git option for now */
500 markfile_in = find_option("import-marks", 0, 1);
501 markfile_out = find_option("export-marks", 0, 1);
502
503 if( !(gexport.zTrunkName = find_option("rename-trunk", 0, 1)) ){
504 gexport.zTrunkName = "trunk";
505 }
506
507 db_find_and_open_repository(0, 2);
508 verify_all_options();
509 if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
510
@@ -547,26 +617,22 @@
617 const char *zSecondsSince1970 = db_column_text(&q, 0);
618 int ckinId = db_column_int(&q, 1);
619 const char *zComment = db_column_text(&q, 2);
620 const char *zUser = db_column_text(&q, 3);
621 const char *zBranch = db_column_text(&q, 4);
 
622 char *zMark;
623
624 bag_insert(&vers, ckinId);
625 db_bind_int(&q2, ":rid", ckinId);
626 db_step(&q2);
627 db_reset(&q2);
628 if( zBranch==0 || fossil_strcmp(zBranch, "trunk")==0 ) zBranch = gexport.zTrunkName;
 
 
 
 
629 zMark = mark_name_from_rid(ckinId, &unused_mark);
630 printf("commit refs/heads/");
631 print_ref(zBranch);
632 printf("\nmark %s\n", zMark);
633 free(zMark);
 
634 printf("committer");
635 print_person(zUser);
636 printf(" %s +0000\n", zSecondsSince1970);
637 if( zComment==0 ) zComment = "null comment";
638 printf("data %d\n%s\n", (int)strlen(zComment), zComment);
@@ -630,33 +696,34 @@
696 manifest_cache_clear();
697
698
699 /* Output tags */
700 db_prepare(&q,
701 "SELECT tagname, rid, strftime('%%s',mtime),"
702 " (SELECT coalesce(euser, user) FROM event WHERE objid=rid),"
703 " value"
704 " FROM tagxref JOIN tag USING(tagid)"
705 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
706 );
707 while( db_step(&q)==SQLITE_ROW ){
708 const char *zTagname = db_column_text(&q, 0);
 
709 int rid = db_column_int(&q, 1);
710 char *zMark = mark_name_from_rid(rid, &unused_mark);
711 const char *zSecSince1970 = db_column_text(&q, 2);
712 const char *zUser = db_column_text(&q, 3);
713 const char *zValue = db_column_text(&q, 4);
714 if( rid==0 || !bag_find(&vers, rid) ) continue;
715 zTagname += 4;
716 printf("tag ");
717 print_ref(zTagname);
718 printf("\nfrom %s\n", zMark);
 
 
 
719 free(zMark);
720 printf("tagger");
721 print_person(zUser);
722 printf(" %s +0000\n", zSecSince1970);
723 printf("data %d\n", zValue==NULL?0:strlen(zValue)+1);
724 if( zValue!=NULL ) printf("%s\n",zValue);
725 }
726 db_finalize(&q);
727
728 if( markfile_out!=0 ){
729 FILE *f;
730
+87 -20
--- src/export.c
+++ src/export.c
@@ -19,10 +19,17 @@
1919
*/
2020
#include "config.h"
2121
#include "export.h"
2222
#include <assert.h>
2323
24
+/*
25
+** State information common to all export types.
26
+*/
27
+static struct {
28
+ const char *zTrunkName; /* Name of trunk branch */
29
+} gexport;
30
+
2431
#if INTERFACE
2532
/*
2633
** struct mark_t
2734
** holds information for translating between git commits
2835
** and fossil commits.
@@ -161,10 +168,68 @@
161168
printf(" %s <%s>", zName, zEmail);
162169
free(zName);
163170
free(zEmail);
164171
db_reset(&q);
165172
}
173
+
174
+#define REFREPLACEMENT '_'
175
+
176
+/*
177
+** Output a sanitized git named reference.
178
+** https://git-scm.com/docs/git-check-ref-format
179
+** This implementation assumes we are only printing
180
+** the branch or tag part of the reference.
181
+*/
182
+static void print_ref(const char *zRef){
183
+ char *zEncoded = mprintf("%s", zRef);
184
+ int i, w;
185
+ if (zEncoded[0]=='@' && zEncoded[1]=='\0'){
186
+ putchar(REFREPLACEMENT);
187
+ return;
188
+ }
189
+ for(i=0, w=0; zEncoded[i]; i++, w++){
190
+ if( i!=0 ){ /* Two letter tests */
191
+ if( (zEncoded[i-1]=='.' && zEncoded[i]=='.') ||
192
+ (zEncoded[i-1]=='@' && zEncoded[i]=='{') ){
193
+ zEncoded[w]=zEncoded[w-1]=REFREPLACEMENT;
194
+ continue;
195
+ }
196
+ if( zEncoded[i-1]=='/' && zEncoded[i]=='/' ){
197
+ w--; /* Normalise to a single / by rolling back w */
198
+ continue;
199
+ }
200
+ }
201
+ /* No control characters */
202
+ if( (unsigned)zEncoded[i]<0x20 || zEncoded[i]==0x7f ){
203
+ zEncoded[w]=REFREPLACEMENT;
204
+ continue;
205
+ }
206
+ switch( zEncoded[i] ){
207
+ case ' ':
208
+ case '^':
209
+ case ':':
210
+ case '?':
211
+ case '*':
212
+ case '[':
213
+ case '\\':
214
+ zEncoded[w]=REFREPLACEMENT;
215
+ break;
216
+ }
217
+ }
218
+ /* Cannot begin with a . or / */
219
+ if( zEncoded[0]=='.' || zEncoded[0] == '/' ) zEncoded[0]=REFREPLACEMENT;
220
+ if( i>0 ){
221
+ i--; w--;
222
+ /* Or end with a . or / */
223
+ if( zEncoded[i]=='.' || zEncoded[i] == '/' ) zEncoded[w]=REFREPLACEMENT;
224
+ /* Cannot end with .lock */
225
+ if ( i>4 && strcmp((zEncoded+i)-5, ".lock")==0 )
226
+ memset((zEncoded+w)-5, REFREPLACEMENT, 5);
227
+ }
228
+ printf("%s", zEncoded);
229
+ free(zEncoded);
230
+}
166231
167232
#define BLOBMARK(rid) ((rid) * 2)
168233
#define COMMITMARK(rid) ((rid) * 2 + 1)
169234
170235
/*
@@ -413,10 +478,11 @@
413478
** blobs written on exit for use with "--import-marks" on the next run.
414479
**
415480
** Options:
416481
** --export-marks FILE export rids of exported data to FILE
417482
** --import-marks FILE read rids of data to ignore from FILE
483
+** --rename-trunk NAME use NAME as name of exported trunk branch
418484
** --repository|-R REPOSITORY export the given REPOSITORY
419485
**
420486
** See also: import
421487
*/
422488
void export_cmd(void){
@@ -431,10 +497,14 @@
431497
bag_init(&vers);
432498
433499
find_option("git", 0, 0); /* Ignore the --git option for now */
434500
markfile_in = find_option("import-marks", 0, 1);
435501
markfile_out = find_option("export-marks", 0, 1);
502
+
503
+ if( !(gexport.zTrunkName = find_option("rename-trunk", 0, 1)) ){
504
+ gexport.zTrunkName = "trunk";
505
+ }
436506
437507
db_find_and_open_repository(0, 2);
438508
verify_all_options();
439509
if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
440510
@@ -547,26 +617,22 @@
547617
const char *zSecondsSince1970 = db_column_text(&q, 0);
548618
int ckinId = db_column_int(&q, 1);
549619
const char *zComment = db_column_text(&q, 2);
550620
const char *zUser = db_column_text(&q, 3);
551621
const char *zBranch = db_column_text(&q, 4);
552
- char *zBr;
553622
char *zMark;
554623
555624
bag_insert(&vers, ckinId);
556625
db_bind_int(&q2, ":rid", ckinId);
557626
db_step(&q2);
558627
db_reset(&q2);
559
- if( zBranch==0 ) zBranch = "trunk";
560
- zBr = mprintf("%s", zBranch);
561
- for(i=0; zBr[i]; i++){
562
- if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
563
- }
628
+ if( zBranch==0 || fossil_strcmp(zBranch, "trunk")==0 ) zBranch = gexport.zTrunkName;
564629
zMark = mark_name_from_rid(ckinId, &unused_mark);
565
- printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
630
+ printf("commit refs/heads/");
631
+ print_ref(zBranch);
632
+ printf("\nmark %s\n", zMark);
566633
free(zMark);
567
- free(zBr);
568634
printf("committer");
569635
print_person(zUser);
570636
printf(" %s +0000\n", zSecondsSince1970);
571637
if( zComment==0 ) zComment = "null comment";
572638
printf("data %d\n%s\n", (int)strlen(zComment), zComment);
@@ -630,33 +696,34 @@
630696
manifest_cache_clear();
631697
632698
633699
/* Output tags */
634700
db_prepare(&q,
635
- "SELECT tagname, rid, strftime('%%s',mtime)"
701
+ "SELECT tagname, rid, strftime('%%s',mtime),"
702
+ " (SELECT coalesce(euser, user) FROM event WHERE objid=rid),"
703
+ " value"
636704
" FROM tagxref JOIN tag USING(tagid)"
637705
" WHERE tagtype=1 AND tagname GLOB 'sym-*'"
638706
);
639707
while( db_step(&q)==SQLITE_ROW ){
640708
const char *zTagname = db_column_text(&q, 0);
641
- char *zEncoded = 0;
642709
int rid = db_column_int(&q, 1);
643710
char *zMark = mark_name_from_rid(rid, &unused_mark);
644711
const char *zSecSince1970 = db_column_text(&q, 2);
645
- int i;
712
+ const char *zUser = db_column_text(&q, 3);
713
+ const char *zValue = db_column_text(&q, 4);
646714
if( rid==0 || !bag_find(&vers, rid) ) continue;
647715
zTagname += 4;
648
- zEncoded = mprintf("%s", zTagname);
649
- for(i=0; zEncoded[i]; i++){
650
- if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
651
- }
652
- printf("tag %s\n", zEncoded);
653
- printf("from %s\n", zMark);
716
+ printf("tag ");
717
+ print_ref(zTagname);
718
+ printf("\nfrom %s\n", zMark);
654719
free(zMark);
655
- printf("tagger <tagger> %s +0000\n", zSecSince1970);
656
- printf("data 0\n");
657
- fossil_free(zEncoded);
720
+ printf("tagger");
721
+ print_person(zUser);
722
+ printf(" %s +0000\n", zSecSince1970);
723
+ printf("data %d\n", zValue==NULL?0:strlen(zValue)+1);
724
+ if( zValue!=NULL ) printf("%s\n",zValue);
658725
}
659726
db_finalize(&q);
660727
661728
if( markfile_out!=0 ){
662729
FILE *f;
663730
--- src/export.c
+++ src/export.c
@@ -19,10 +19,17 @@
19 */
20 #include "config.h"
21 #include "export.h"
22 #include <assert.h>
23
 
 
 
 
 
 
 
24 #if INTERFACE
25 /*
26 ** struct mark_t
27 ** holds information for translating between git commits
28 ** and fossil commits.
@@ -161,10 +168,68 @@
161 printf(" %s <%s>", zName, zEmail);
162 free(zName);
163 free(zEmail);
164 db_reset(&q);
165 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
167 #define BLOBMARK(rid) ((rid) * 2)
168 #define COMMITMARK(rid) ((rid) * 2 + 1)
169
170 /*
@@ -413,10 +478,11 @@
413 ** blobs written on exit for use with "--import-marks" on the next run.
414 **
415 ** Options:
416 ** --export-marks FILE export rids of exported data to FILE
417 ** --import-marks FILE read rids of data to ignore from FILE
 
418 ** --repository|-R REPOSITORY export the given REPOSITORY
419 **
420 ** See also: import
421 */
422 void export_cmd(void){
@@ -431,10 +497,14 @@
431 bag_init(&vers);
432
433 find_option("git", 0, 0); /* Ignore the --git option for now */
434 markfile_in = find_option("import-marks", 0, 1);
435 markfile_out = find_option("export-marks", 0, 1);
 
 
 
 
436
437 db_find_and_open_repository(0, 2);
438 verify_all_options();
439 if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
440
@@ -547,26 +617,22 @@
547 const char *zSecondsSince1970 = db_column_text(&q, 0);
548 int ckinId = db_column_int(&q, 1);
549 const char *zComment = db_column_text(&q, 2);
550 const char *zUser = db_column_text(&q, 3);
551 const char *zBranch = db_column_text(&q, 4);
552 char *zBr;
553 char *zMark;
554
555 bag_insert(&vers, ckinId);
556 db_bind_int(&q2, ":rid", ckinId);
557 db_step(&q2);
558 db_reset(&q2);
559 if( zBranch==0 ) zBranch = "trunk";
560 zBr = mprintf("%s", zBranch);
561 for(i=0; zBr[i]; i++){
562 if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
563 }
564 zMark = mark_name_from_rid(ckinId, &unused_mark);
565 printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
 
 
566 free(zMark);
567 free(zBr);
568 printf("committer");
569 print_person(zUser);
570 printf(" %s +0000\n", zSecondsSince1970);
571 if( zComment==0 ) zComment = "null comment";
572 printf("data %d\n%s\n", (int)strlen(zComment), zComment);
@@ -630,33 +696,34 @@
630 manifest_cache_clear();
631
632
633 /* Output tags */
634 db_prepare(&q,
635 "SELECT tagname, rid, strftime('%%s',mtime)"
 
 
636 " FROM tagxref JOIN tag USING(tagid)"
637 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
638 );
639 while( db_step(&q)==SQLITE_ROW ){
640 const char *zTagname = db_column_text(&q, 0);
641 char *zEncoded = 0;
642 int rid = db_column_int(&q, 1);
643 char *zMark = mark_name_from_rid(rid, &unused_mark);
644 const char *zSecSince1970 = db_column_text(&q, 2);
645 int i;
 
646 if( rid==0 || !bag_find(&vers, rid) ) continue;
647 zTagname += 4;
648 zEncoded = mprintf("%s", zTagname);
649 for(i=0; zEncoded[i]; i++){
650 if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
651 }
652 printf("tag %s\n", zEncoded);
653 printf("from %s\n", zMark);
654 free(zMark);
655 printf("tagger <tagger> %s +0000\n", zSecSince1970);
656 printf("data 0\n");
657 fossil_free(zEncoded);
 
 
658 }
659 db_finalize(&q);
660
661 if( markfile_out!=0 ){
662 FILE *f;
663
--- src/export.c
+++ src/export.c
@@ -19,10 +19,17 @@
19 */
20 #include "config.h"
21 #include "export.h"
22 #include <assert.h>
23
24 /*
25 ** State information common to all export types.
26 */
27 static struct {
28 const char *zTrunkName; /* Name of trunk branch */
29 } gexport;
30
31 #if INTERFACE
32 /*
33 ** struct mark_t
34 ** holds information for translating between git commits
35 ** and fossil commits.
@@ -161,10 +168,68 @@
168 printf(" %s <%s>", zName, zEmail);
169 free(zName);
170 free(zEmail);
171 db_reset(&q);
172 }
173
174 #define REFREPLACEMENT '_'
175
176 /*
177 ** Output a sanitized git named reference.
178 ** https://git-scm.com/docs/git-check-ref-format
179 ** This implementation assumes we are only printing
180 ** the branch or tag part of the reference.
181 */
182 static void print_ref(const char *zRef){
183 char *zEncoded = mprintf("%s", zRef);
184 int i, w;
185 if (zEncoded[0]=='@' && zEncoded[1]=='\0'){
186 putchar(REFREPLACEMENT);
187 return;
188 }
189 for(i=0, w=0; zEncoded[i]; i++, w++){
190 if( i!=0 ){ /* Two letter tests */
191 if( (zEncoded[i-1]=='.' && zEncoded[i]=='.') ||
192 (zEncoded[i-1]=='@' && zEncoded[i]=='{') ){
193 zEncoded[w]=zEncoded[w-1]=REFREPLACEMENT;
194 continue;
195 }
196 if( zEncoded[i-1]=='/' && zEncoded[i]=='/' ){
197 w--; /* Normalise to a single / by rolling back w */
198 continue;
199 }
200 }
201 /* No control characters */
202 if( (unsigned)zEncoded[i]<0x20 || zEncoded[i]==0x7f ){
203 zEncoded[w]=REFREPLACEMENT;
204 continue;
205 }
206 switch( zEncoded[i] ){
207 case ' ':
208 case '^':
209 case ':':
210 case '?':
211 case '*':
212 case '[':
213 case '\\':
214 zEncoded[w]=REFREPLACEMENT;
215 break;
216 }
217 }
218 /* Cannot begin with a . or / */
219 if( zEncoded[0]=='.' || zEncoded[0] == '/' ) zEncoded[0]=REFREPLACEMENT;
220 if( i>0 ){
221 i--; w--;
222 /* Or end with a . or / */
223 if( zEncoded[i]=='.' || zEncoded[i] == '/' ) zEncoded[w]=REFREPLACEMENT;
224 /* Cannot end with .lock */
225 if ( i>4 && strcmp((zEncoded+i)-5, ".lock")==0 )
226 memset((zEncoded+w)-5, REFREPLACEMENT, 5);
227 }
228 printf("%s", zEncoded);
229 free(zEncoded);
230 }
231
232 #define BLOBMARK(rid) ((rid) * 2)
233 #define COMMITMARK(rid) ((rid) * 2 + 1)
234
235 /*
@@ -413,10 +478,11 @@
478 ** blobs written on exit for use with "--import-marks" on the next run.
479 **
480 ** Options:
481 ** --export-marks FILE export rids of exported data to FILE
482 ** --import-marks FILE read rids of data to ignore from FILE
483 ** --rename-trunk NAME use NAME as name of exported trunk branch
484 ** --repository|-R REPOSITORY export the given REPOSITORY
485 **
486 ** See also: import
487 */
488 void export_cmd(void){
@@ -431,10 +497,14 @@
497 bag_init(&vers);
498
499 find_option("git", 0, 0); /* Ignore the --git option for now */
500 markfile_in = find_option("import-marks", 0, 1);
501 markfile_out = find_option("export-marks", 0, 1);
502
503 if( !(gexport.zTrunkName = find_option("rename-trunk", 0, 1)) ){
504 gexport.zTrunkName = "trunk";
505 }
506
507 db_find_and_open_repository(0, 2);
508 verify_all_options();
509 if( g.argc!=2 && g.argc!=3 ){ usage("--git ?REPOSITORY?"); }
510
@@ -547,26 +617,22 @@
617 const char *zSecondsSince1970 = db_column_text(&q, 0);
618 int ckinId = db_column_int(&q, 1);
619 const char *zComment = db_column_text(&q, 2);
620 const char *zUser = db_column_text(&q, 3);
621 const char *zBranch = db_column_text(&q, 4);
 
622 char *zMark;
623
624 bag_insert(&vers, ckinId);
625 db_bind_int(&q2, ":rid", ckinId);
626 db_step(&q2);
627 db_reset(&q2);
628 if( zBranch==0 || fossil_strcmp(zBranch, "trunk")==0 ) zBranch = gexport.zTrunkName;
 
 
 
 
629 zMark = mark_name_from_rid(ckinId, &unused_mark);
630 printf("commit refs/heads/");
631 print_ref(zBranch);
632 printf("\nmark %s\n", zMark);
633 free(zMark);
 
634 printf("committer");
635 print_person(zUser);
636 printf(" %s +0000\n", zSecondsSince1970);
637 if( zComment==0 ) zComment = "null comment";
638 printf("data %d\n%s\n", (int)strlen(zComment), zComment);
@@ -630,33 +696,34 @@
696 manifest_cache_clear();
697
698
699 /* Output tags */
700 db_prepare(&q,
701 "SELECT tagname, rid, strftime('%%s',mtime),"
702 " (SELECT coalesce(euser, user) FROM event WHERE objid=rid),"
703 " value"
704 " FROM tagxref JOIN tag USING(tagid)"
705 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
706 );
707 while( db_step(&q)==SQLITE_ROW ){
708 const char *zTagname = db_column_text(&q, 0);
 
709 int rid = db_column_int(&q, 1);
710 char *zMark = mark_name_from_rid(rid, &unused_mark);
711 const char *zSecSince1970 = db_column_text(&q, 2);
712 const char *zUser = db_column_text(&q, 3);
713 const char *zValue = db_column_text(&q, 4);
714 if( rid==0 || !bag_find(&vers, rid) ) continue;
715 zTagname += 4;
716 printf("tag ");
717 print_ref(zTagname);
718 printf("\nfrom %s\n", zMark);
 
 
 
719 free(zMark);
720 printf("tagger");
721 print_person(zUser);
722 printf(" %s +0000\n", zSecSince1970);
723 printf("data %d\n", zValue==NULL?0:strlen(zValue)+1);
724 if( zValue!=NULL ) printf("%s\n",zValue);
725 }
726 db_finalize(&q);
727
728 if( markfile_out!=0 ){
729 FILE *f;
730
+48 -22
--- src/import.c
+++ src/import.c
@@ -215,13 +215,16 @@
215215
static void finish_tag(void){
216216
Blob record, cksum;
217217
if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
218218
blob_zero(&record);
219219
blob_appendf(&record, "D %s\n", gg.zDate);
220
- blob_appendf(&record, "T +%F%F%F %s\n", gimport.zTagPre, gg.zTag,
220
+ blob_appendf(&record, "T +sym-%F%F%F %s", gimport.zTagPre, gg.zTag,
221221
gimport.zTagSuf, gg.zFrom);
222
- blob_appendf(&record, "U %F\n", gg.zUser);
222
+ if( gg.zComment ){
223
+ blob_appendf(&record, " %F", gg.zComment);
224
+ }
225
+ blob_appendf(&record, "\nU %F\n", gg.zUser);
223226
md5sum_blob(&record, &cksum);
224227
blob_appendf(&record, "Z %b\n", &cksum);
225228
fast_insert_content(&record, 0, 0, 1);
226229
blob_reset(&cksum);
227230
}
@@ -511,10 +514,14 @@
511514
}
512515
zName[i] = 0;
513516
}
514517
515518
519
+static struct{
520
+ const char *zMasterName; /* Name of master branch */
521
+} ggit;
522
+
516523
/*
517524
** Read the git-fast-import format from pIn and insert the corresponding
518525
** content into the database.
519526
*/
520527
static void git_fast_import(FILE *pIn){
@@ -534,14 +541,15 @@
534541
if( strncmp(zLine, "blob", 4)==0 ){
535542
gg.xFinish();
536543
gg.xFinish = finish_blob;
537544
}else
538545
if( strncmp(zLine, "commit ", 7)==0 ){
546
+ const char *zRefName;
539547
gg.xFinish();
540548
gg.xFinish = finish_commit;
541549
trim_newline(&zLine[7]);
542
- z = &zLine[7];
550
+ zRefName = &zLine[7];
543551
544552
/* The argument to the "commit" line might match either of these
545553
** patterns:
546554
**
547555
** (A) refs/heads/BRANCHNAME
@@ -557,15 +565,15 @@
557565
** last commit that holds that tag.
558566
**
559567
** None of the above is explained in the git-fast-export
560568
** documentation. We had to figure it out via trial and error.
561569
*/
562
- for(i=5; i<strlen(z) && z[i]!='/'; i++){}
563
- gg.tagCommit = strncmp(&z[5], "tags", 4)==0; /* True for pattern B */
564
- if( z[i+1]!=0 ) z += i+1;
565
- if( fossil_strcmp(z, "master")==0 ) z = "trunk";
566
- gg.zBranch = fossil_strdup(z);
570
+ for(i=5; i<strlen(zRefName) && zRefName[i]!='/'; i++){}
571
+ gg.tagCommit = strncmp(&zRefName[5], "tags", 4)==0; /* True for pattern B */
572
+ if( zRefName[i+1]!=0 ) zRefName += i+1;
573
+ if( fossil_strcmp(zRefName, "master")==0 ) zRefName = ggit.zMasterName;
574
+ gg.zBranch = fossil_strdup(zRefName);
567575
gg.fromLoaded = 0;
568576
}else
569577
if( strncmp(zLine, "tag ", 4)==0 ){
570578
gg.xFinish();
571579
gg.xFinish = finish_tag;
@@ -598,12 +606,16 @@
598606
gg.aData = fossil_malloc( gg.nData+1 );
599607
got = fread(gg.aData, 1, gg.nData, pIn);
600608
if( got!=gg.nData ){
601609
fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
602610
}
603
- gg.aData[got] = 0;
604
- if( gg.zComment==0 && gg.xFinish==finish_commit ){
611
+ gg.aData[got] = '\0';
612
+ if( gg.zComment==0 &&
613
+ (gg.xFinish==finish_commit || gg.xFinish==finish_tag) ){
614
+ /* Strip trailing newline, it's appended to the comment. */
615
+ if( gg.aData[got-1] == '\n' )
616
+ gg.aData[got-1] = '\0';
605617
gg.zComment = gg.aData;
606618
gg.aData = 0;
607619
gg.nData = 0;
608620
}
609621
}
@@ -616,21 +628,28 @@
616628
fossil_free(gg.zMark);
617629
gg.zMark = fossil_strdup(&zLine[5]);
618630
}else
619631
if( strncmp(zLine, "tagger ", 7)==0 || strncmp(zLine, "committer ",10)==0 ){
620632
sqlite3_int64 secSince1970;
621
- for(i=0; zLine[i] && zLine[i]!='<'; i++){}
622
- if( zLine[i]==0 ) goto malformed_line;
623
- z = &zLine[i+1];
624
- for(i=i+1; zLine[i] && zLine[i]!='>'; i++){}
625
- if( zLine[i]==0 ) goto malformed_line;
626
- zLine[i] = 0;
633
+ z = strchr(zLine, ' ');
634
+ while( fossil_isspace(*z) ) z++;
635
+ if( (zTo=strchr(z, '>'))==NULL ) goto malformed_line;
636
+ *(++zTo) = '\0';
637
+ /* Lookup user by contact info. */
627638
fossil_free(gg.zUser);
628
- gg.zUser = fossil_strdup(z);
639
+ gg.zUser = db_text(0, "SELECT login FROM user WHERE info=%Q", z);
640
+ if( gg.zUser==NULL ){
641
+ /* If there is no user with this contact info,
642
+ * then use the email address as the username. */
643
+ if ( (z=strchr(z, '<'))==NULL ) goto malformed_line;
644
+ z++;
645
+ *(zTo-1) = '\0';
646
+ gg.zUser = fossil_strdup(z);
647
+ }
629648
secSince1970 = 0;
630
- for(i=i+2; fossil_isdigit(zLine[i]); i++){
631
- secSince1970 = secSince1970*10 + zLine[i] - '0';
649
+ for(zTo++; fossil_isdigit(*zTo); zTo++){
650
+ secSince1970 = secSince1970*10 + *zTo - '0';
632651
}
633652
fossil_free(gg.zDate);
634653
gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970);
635654
gg.zDate[10] = 'T';
636655
}else
@@ -1580,12 +1599,13 @@
15801599
**
15811600
** The following formats are currently understood by this command
15821601
**
15831602
** --git Import from the git-fast-export file format (default)
15841603
** Options:
1585
-** --import-marks FILE Restore marks table from FILE
1586
-** --export-marks FILE Save marks table to FILE
1604
+** --import-marks FILE Restore marks table from FILE
1605
+** --export-marks FILE Save marks table to FILE
1606
+** --rename-master NAME Renames the master branch to NAME
15871607
**
15881608
** --svn Import from the svnadmin-dump file format. The default
15891609
** behaviour (unless overridden by --flat) is to treat 3
15901610
** folders in the SVN root as special, following the
15911611
** common layout of SVN repositories. These are (by
@@ -1703,10 +1723,13 @@
17031723
gsvn.revFlag = find_option("rev-tags", 0, 0)
17041724
|| (incrFlag && !find_option("no-rev-tags", 0, 0));
17051725
}else if( gitFlag ){
17061726
markfile_in = find_option("import-marks", 0, 1);
17071727
markfile_out = find_option("export-marks", 0, 1);
1728
+ if( !(ggit.zMasterName = find_option("rename-master", 0, 1)) ){
1729
+ ggit.zMasterName = "master";
1730
+ }
17081731
}
17091732
verify_all_options();
17101733
17111734
if( g.argc!=3 && g.argc!=4 ){
17121735
usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
@@ -1723,11 +1746,14 @@
17231746
}
17241747
db_open_repository(g.argv[2]);
17251748
db_open_config(0, 0);
17261749
17271750
db_begin_transaction();
1728
- if( !incrFlag ) db_initial_setup(0, 0, 0);
1751
+ if( !incrFlag ){
1752
+ db_initial_setup(0, 0, 0);
1753
+ db_set("main-branch", gimport.zTrunkName, 0);
1754
+ }
17291755
17301756
if( svnFlag ){
17311757
db_multi_exec(
17321758
"CREATE TEMP TABLE xrevisions("
17331759
" trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
17341760
--- src/import.c
+++ src/import.c
@@ -215,13 +215,16 @@
215 static void finish_tag(void){
216 Blob record, cksum;
217 if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
218 blob_zero(&record);
219 blob_appendf(&record, "D %s\n", gg.zDate);
220 blob_appendf(&record, "T +%F%F%F %s\n", gimport.zTagPre, gg.zTag,
221 gimport.zTagSuf, gg.zFrom);
222 blob_appendf(&record, "U %F\n", gg.zUser);
 
 
 
223 md5sum_blob(&record, &cksum);
224 blob_appendf(&record, "Z %b\n", &cksum);
225 fast_insert_content(&record, 0, 0, 1);
226 blob_reset(&cksum);
227 }
@@ -511,10 +514,14 @@
511 }
512 zName[i] = 0;
513 }
514
515
 
 
 
 
516 /*
517 ** Read the git-fast-import format from pIn and insert the corresponding
518 ** content into the database.
519 */
520 static void git_fast_import(FILE *pIn){
@@ -534,14 +541,15 @@
534 if( strncmp(zLine, "blob", 4)==0 ){
535 gg.xFinish();
536 gg.xFinish = finish_blob;
537 }else
538 if( strncmp(zLine, "commit ", 7)==0 ){
 
539 gg.xFinish();
540 gg.xFinish = finish_commit;
541 trim_newline(&zLine[7]);
542 z = &zLine[7];
543
544 /* The argument to the "commit" line might match either of these
545 ** patterns:
546 **
547 ** (A) refs/heads/BRANCHNAME
@@ -557,15 +565,15 @@
557 ** last commit that holds that tag.
558 **
559 ** None of the above is explained in the git-fast-export
560 ** documentation. We had to figure it out via trial and error.
561 */
562 for(i=5; i<strlen(z) && z[i]!='/'; i++){}
563 gg.tagCommit = strncmp(&z[5], "tags", 4)==0; /* True for pattern B */
564 if( z[i+1]!=0 ) z += i+1;
565 if( fossil_strcmp(z, "master")==0 ) z = "trunk";
566 gg.zBranch = fossil_strdup(z);
567 gg.fromLoaded = 0;
568 }else
569 if( strncmp(zLine, "tag ", 4)==0 ){
570 gg.xFinish();
571 gg.xFinish = finish_tag;
@@ -598,12 +606,16 @@
598 gg.aData = fossil_malloc( gg.nData+1 );
599 got = fread(gg.aData, 1, gg.nData, pIn);
600 if( got!=gg.nData ){
601 fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
602 }
603 gg.aData[got] = 0;
604 if( gg.zComment==0 && gg.xFinish==finish_commit ){
 
 
 
 
605 gg.zComment = gg.aData;
606 gg.aData = 0;
607 gg.nData = 0;
608 }
609 }
@@ -616,21 +628,28 @@
616 fossil_free(gg.zMark);
617 gg.zMark = fossil_strdup(&zLine[5]);
618 }else
619 if( strncmp(zLine, "tagger ", 7)==0 || strncmp(zLine, "committer ",10)==0 ){
620 sqlite3_int64 secSince1970;
621 for(i=0; zLine[i] && zLine[i]!='<'; i++){}
622 if( zLine[i]==0 ) goto malformed_line;
623 z = &zLine[i+1];
624 for(i=i+1; zLine[i] && zLine[i]!='>'; i++){}
625 if( zLine[i]==0 ) goto malformed_line;
626 zLine[i] = 0;
627 fossil_free(gg.zUser);
628 gg.zUser = fossil_strdup(z);
 
 
 
 
 
 
 
 
629 secSince1970 = 0;
630 for(i=i+2; fossil_isdigit(zLine[i]); i++){
631 secSince1970 = secSince1970*10 + zLine[i] - '0';
632 }
633 fossil_free(gg.zDate);
634 gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970);
635 gg.zDate[10] = 'T';
636 }else
@@ -1580,12 +1599,13 @@
1580 **
1581 ** The following formats are currently understood by this command
1582 **
1583 ** --git Import from the git-fast-export file format (default)
1584 ** Options:
1585 ** --import-marks FILE Restore marks table from FILE
1586 ** --export-marks FILE Save marks table to FILE
 
1587 **
1588 ** --svn Import from the svnadmin-dump file format. The default
1589 ** behaviour (unless overridden by --flat) is to treat 3
1590 ** folders in the SVN root as special, following the
1591 ** common layout of SVN repositories. These are (by
@@ -1703,10 +1723,13 @@
1703 gsvn.revFlag = find_option("rev-tags", 0, 0)
1704 || (incrFlag && !find_option("no-rev-tags", 0, 0));
1705 }else if( gitFlag ){
1706 markfile_in = find_option("import-marks", 0, 1);
1707 markfile_out = find_option("export-marks", 0, 1);
 
 
 
1708 }
1709 verify_all_options();
1710
1711 if( g.argc!=3 && g.argc!=4 ){
1712 usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
@@ -1723,11 +1746,14 @@
1723 }
1724 db_open_repository(g.argv[2]);
1725 db_open_config(0, 0);
1726
1727 db_begin_transaction();
1728 if( !incrFlag ) db_initial_setup(0, 0, 0);
 
 
 
1729
1730 if( svnFlag ){
1731 db_multi_exec(
1732 "CREATE TEMP TABLE xrevisions("
1733 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1734
--- src/import.c
+++ src/import.c
@@ -215,13 +215,16 @@
215 static void finish_tag(void){
216 Blob record, cksum;
217 if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
218 blob_zero(&record);
219 blob_appendf(&record, "D %s\n", gg.zDate);
220 blob_appendf(&record, "T +sym-%F%F%F %s", gimport.zTagPre, gg.zTag,
221 gimport.zTagSuf, gg.zFrom);
222 if( gg.zComment ){
223 blob_appendf(&record, " %F", gg.zComment);
224 }
225 blob_appendf(&record, "\nU %F\n", gg.zUser);
226 md5sum_blob(&record, &cksum);
227 blob_appendf(&record, "Z %b\n", &cksum);
228 fast_insert_content(&record, 0, 0, 1);
229 blob_reset(&cksum);
230 }
@@ -511,10 +514,14 @@
514 }
515 zName[i] = 0;
516 }
517
518
519 static struct{
520 const char *zMasterName; /* Name of master branch */
521 } ggit;
522
523 /*
524 ** Read the git-fast-import format from pIn and insert the corresponding
525 ** content into the database.
526 */
527 static void git_fast_import(FILE *pIn){
@@ -534,14 +541,15 @@
541 if( strncmp(zLine, "blob", 4)==0 ){
542 gg.xFinish();
543 gg.xFinish = finish_blob;
544 }else
545 if( strncmp(zLine, "commit ", 7)==0 ){
546 const char *zRefName;
547 gg.xFinish();
548 gg.xFinish = finish_commit;
549 trim_newline(&zLine[7]);
550 zRefName = &zLine[7];
551
552 /* The argument to the "commit" line might match either of these
553 ** patterns:
554 **
555 ** (A) refs/heads/BRANCHNAME
@@ -557,15 +565,15 @@
565 ** last commit that holds that tag.
566 **
567 ** None of the above is explained in the git-fast-export
568 ** documentation. We had to figure it out via trial and error.
569 */
570 for(i=5; i<strlen(zRefName) && zRefName[i]!='/'; i++){}
571 gg.tagCommit = strncmp(&zRefName[5], "tags", 4)==0; /* True for pattern B */
572 if( zRefName[i+1]!=0 ) zRefName += i+1;
573 if( fossil_strcmp(zRefName, "master")==0 ) zRefName = ggit.zMasterName;
574 gg.zBranch = fossil_strdup(zRefName);
575 gg.fromLoaded = 0;
576 }else
577 if( strncmp(zLine, "tag ", 4)==0 ){
578 gg.xFinish();
579 gg.xFinish = finish_tag;
@@ -598,12 +606,16 @@
606 gg.aData = fossil_malloc( gg.nData+1 );
607 got = fread(gg.aData, 1, gg.nData, pIn);
608 if( got!=gg.nData ){
609 fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
610 }
611 gg.aData[got] = '\0';
612 if( gg.zComment==0 &&
613 (gg.xFinish==finish_commit || gg.xFinish==finish_tag) ){
614 /* Strip trailing newline, it's appended to the comment. */
615 if( gg.aData[got-1] == '\n' )
616 gg.aData[got-1] = '\0';
617 gg.zComment = gg.aData;
618 gg.aData = 0;
619 gg.nData = 0;
620 }
621 }
@@ -616,21 +628,28 @@
628 fossil_free(gg.zMark);
629 gg.zMark = fossil_strdup(&zLine[5]);
630 }else
631 if( strncmp(zLine, "tagger ", 7)==0 || strncmp(zLine, "committer ",10)==0 ){
632 sqlite3_int64 secSince1970;
633 z = strchr(zLine, ' ');
634 while( fossil_isspace(*z) ) z++;
635 if( (zTo=strchr(z, '>'))==NULL ) goto malformed_line;
636 *(++zTo) = '\0';
637 /* Lookup user by contact info. */
 
638 fossil_free(gg.zUser);
639 gg.zUser = db_text(0, "SELECT login FROM user WHERE info=%Q", z);
640 if( gg.zUser==NULL ){
641 /* If there is no user with this contact info,
642 * then use the email address as the username. */
643 if ( (z=strchr(z, '<'))==NULL ) goto malformed_line;
644 z++;
645 *(zTo-1) = '\0';
646 gg.zUser = fossil_strdup(z);
647 }
648 secSince1970 = 0;
649 for(zTo++; fossil_isdigit(*zTo); zTo++){
650 secSince1970 = secSince1970*10 + *zTo - '0';
651 }
652 fossil_free(gg.zDate);
653 gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970);
654 gg.zDate[10] = 'T';
655 }else
@@ -1580,12 +1599,13 @@
1599 **
1600 ** The following formats are currently understood by this command
1601 **
1602 ** --git Import from the git-fast-export file format (default)
1603 ** Options:
1604 ** --import-marks FILE Restore marks table from FILE
1605 ** --export-marks FILE Save marks table to FILE
1606 ** --rename-master NAME Renames the master branch to NAME
1607 **
1608 ** --svn Import from the svnadmin-dump file format. The default
1609 ** behaviour (unless overridden by --flat) is to treat 3
1610 ** folders in the SVN root as special, following the
1611 ** common layout of SVN repositories. These are (by
@@ -1703,10 +1723,13 @@
1723 gsvn.revFlag = find_option("rev-tags", 0, 0)
1724 || (incrFlag && !find_option("no-rev-tags", 0, 0));
1725 }else if( gitFlag ){
1726 markfile_in = find_option("import-marks", 0, 1);
1727 markfile_out = find_option("export-marks", 0, 1);
1728 if( !(ggit.zMasterName = find_option("rename-master", 0, 1)) ){
1729 ggit.zMasterName = "master";
1730 }
1731 }
1732 verify_all_options();
1733
1734 if( g.argc!=3 && g.argc!=4 ){
1735 usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
@@ -1723,11 +1746,14 @@
1746 }
1747 db_open_repository(g.argv[2]);
1748 db_open_config(0, 0);
1749
1750 db_begin_transaction();
1751 if( !incrFlag ){
1752 db_initial_setup(0, 0, 0);
1753 db_set("main-branch", gimport.zTrunkName, 0);
1754 }
1755
1756 if( svnFlag ){
1757 db_multi_exec(
1758 "CREATE TEMP TABLE xrevisions("
1759 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1760
+48 -22
--- src/import.c
+++ src/import.c
@@ -215,13 +215,16 @@
215215
static void finish_tag(void){
216216
Blob record, cksum;
217217
if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
218218
blob_zero(&record);
219219
blob_appendf(&record, "D %s\n", gg.zDate);
220
- blob_appendf(&record, "T +%F%F%F %s\n", gimport.zTagPre, gg.zTag,
220
+ blob_appendf(&record, "T +sym-%F%F%F %s", gimport.zTagPre, gg.zTag,
221221
gimport.zTagSuf, gg.zFrom);
222
- blob_appendf(&record, "U %F\n", gg.zUser);
222
+ if( gg.zComment ){
223
+ blob_appendf(&record, " %F", gg.zComment);
224
+ }
225
+ blob_appendf(&record, "\nU %F\n", gg.zUser);
223226
md5sum_blob(&record, &cksum);
224227
blob_appendf(&record, "Z %b\n", &cksum);
225228
fast_insert_content(&record, 0, 0, 1);
226229
blob_reset(&cksum);
227230
}
@@ -511,10 +514,14 @@
511514
}
512515
zName[i] = 0;
513516
}
514517
515518
519
+static struct{
520
+ const char *zMasterName; /* Name of master branch */
521
+} ggit;
522
+
516523
/*
517524
** Read the git-fast-import format from pIn and insert the corresponding
518525
** content into the database.
519526
*/
520527
static void git_fast_import(FILE *pIn){
@@ -534,14 +541,15 @@
534541
if( strncmp(zLine, "blob", 4)==0 ){
535542
gg.xFinish();
536543
gg.xFinish = finish_blob;
537544
}else
538545
if( strncmp(zLine, "commit ", 7)==0 ){
546
+ const char *zRefName;
539547
gg.xFinish();
540548
gg.xFinish = finish_commit;
541549
trim_newline(&zLine[7]);
542
- z = &zLine[7];
550
+ zRefName = &zLine[7];
543551
544552
/* The argument to the "commit" line might match either of these
545553
** patterns:
546554
**
547555
** (A) refs/heads/BRANCHNAME
@@ -557,15 +565,15 @@
557565
** last commit that holds that tag.
558566
**
559567
** None of the above is explained in the git-fast-export
560568
** documentation. We had to figure it out via trial and error.
561569
*/
562
- for(i=5; i<strlen(z) && z[i]!='/'; i++){}
563
- gg.tagCommit = strncmp(&z[5], "tags", 4)==0; /* True for pattern B */
564
- if( z[i+1]!=0 ) z += i+1;
565
- if( fossil_strcmp(z, "master")==0 ) z = "trunk";
566
- gg.zBranch = fossil_strdup(z);
570
+ for(i=5; i<strlen(zRefName) && zRefName[i]!='/'; i++){}
571
+ gg.tagCommit = strncmp(&zRefName[5], "tags", 4)==0; /* True for pattern B */
572
+ if( zRefName[i+1]!=0 ) zRefName += i+1;
573
+ if( fossil_strcmp(zRefName, "master")==0 ) zRefName = ggit.zMasterName;
574
+ gg.zBranch = fossil_strdup(zRefName);
567575
gg.fromLoaded = 0;
568576
}else
569577
if( strncmp(zLine, "tag ", 4)==0 ){
570578
gg.xFinish();
571579
gg.xFinish = finish_tag;
@@ -598,12 +606,16 @@
598606
gg.aData = fossil_malloc( gg.nData+1 );
599607
got = fread(gg.aData, 1, gg.nData, pIn);
600608
if( got!=gg.nData ){
601609
fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
602610
}
603
- gg.aData[got] = 0;
604
- if( gg.zComment==0 && gg.xFinish==finish_commit ){
611
+ gg.aData[got] = '\0';
612
+ if( gg.zComment==0 &&
613
+ (gg.xFinish==finish_commit || gg.xFinish==finish_tag) ){
614
+ /* Strip trailing newline, it's appended to the comment. */
615
+ if( gg.aData[got-1] == '\n' )
616
+ gg.aData[got-1] = '\0';
605617
gg.zComment = gg.aData;
606618
gg.aData = 0;
607619
gg.nData = 0;
608620
}
609621
}
@@ -616,21 +628,28 @@
616628
fossil_free(gg.zMark);
617629
gg.zMark = fossil_strdup(&zLine[5]);
618630
}else
619631
if( strncmp(zLine, "tagger ", 7)==0 || strncmp(zLine, "committer ",10)==0 ){
620632
sqlite3_int64 secSince1970;
621
- for(i=0; zLine[i] && zLine[i]!='<'; i++){}
622
- if( zLine[i]==0 ) goto malformed_line;
623
- z = &zLine[i+1];
624
- for(i=i+1; zLine[i] && zLine[i]!='>'; i++){}
625
- if( zLine[i]==0 ) goto malformed_line;
626
- zLine[i] = 0;
633
+ z = strchr(zLine, ' ');
634
+ while( fossil_isspace(*z) ) z++;
635
+ if( (zTo=strchr(z, '>'))==NULL ) goto malformed_line;
636
+ *(++zTo) = '\0';
637
+ /* Lookup user by contact info. */
627638
fossil_free(gg.zUser);
628
- gg.zUser = fossil_strdup(z);
639
+ gg.zUser = db_text(0, "SELECT login FROM user WHERE info=%Q", z);
640
+ if( gg.zUser==NULL ){
641
+ /* If there is no user with this contact info,
642
+ * then use the email address as the username. */
643
+ if ( (z=strchr(z, '<'))==NULL ) goto malformed_line;
644
+ z++;
645
+ *(zTo-1) = '\0';
646
+ gg.zUser = fossil_strdup(z);
647
+ }
629648
secSince1970 = 0;
630
- for(i=i+2; fossil_isdigit(zLine[i]); i++){
631
- secSince1970 = secSince1970*10 + zLine[i] - '0';
649
+ for(zTo++; fossil_isdigit(*zTo); zTo++){
650
+ secSince1970 = secSince1970*10 + *zTo - '0';
632651
}
633652
fossil_free(gg.zDate);
634653
gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970);
635654
gg.zDate[10] = 'T';
636655
}else
@@ -1580,12 +1599,13 @@
15801599
**
15811600
** The following formats are currently understood by this command
15821601
**
15831602
** --git Import from the git-fast-export file format (default)
15841603
** Options:
1585
-** --import-marks FILE Restore marks table from FILE
1586
-** --export-marks FILE Save marks table to FILE
1604
+** --import-marks FILE Restore marks table from FILE
1605
+** --export-marks FILE Save marks table to FILE
1606
+** --rename-master NAME Renames the master branch to NAME
15871607
**
15881608
** --svn Import from the svnadmin-dump file format. The default
15891609
** behaviour (unless overridden by --flat) is to treat 3
15901610
** folders in the SVN root as special, following the
15911611
** common layout of SVN repositories. These are (by
@@ -1703,10 +1723,13 @@
17031723
gsvn.revFlag = find_option("rev-tags", 0, 0)
17041724
|| (incrFlag && !find_option("no-rev-tags", 0, 0));
17051725
}else if( gitFlag ){
17061726
markfile_in = find_option("import-marks", 0, 1);
17071727
markfile_out = find_option("export-marks", 0, 1);
1728
+ if( !(ggit.zMasterName = find_option("rename-master", 0, 1)) ){
1729
+ ggit.zMasterName = "master";
1730
+ }
17081731
}
17091732
verify_all_options();
17101733
17111734
if( g.argc!=3 && g.argc!=4 ){
17121735
usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
@@ -1723,11 +1746,14 @@
17231746
}
17241747
db_open_repository(g.argv[2]);
17251748
db_open_config(0, 0);
17261749
17271750
db_begin_transaction();
1728
- if( !incrFlag ) db_initial_setup(0, 0, 0);
1751
+ if( !incrFlag ){
1752
+ db_initial_setup(0, 0, 0);
1753
+ db_set("main-branch", gimport.zTrunkName, 0);
1754
+ }
17291755
17301756
if( svnFlag ){
17311757
db_multi_exec(
17321758
"CREATE TEMP TABLE xrevisions("
17331759
" trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
17341760
--- src/import.c
+++ src/import.c
@@ -215,13 +215,16 @@
215 static void finish_tag(void){
216 Blob record, cksum;
217 if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
218 blob_zero(&record);
219 blob_appendf(&record, "D %s\n", gg.zDate);
220 blob_appendf(&record, "T +%F%F%F %s\n", gimport.zTagPre, gg.zTag,
221 gimport.zTagSuf, gg.zFrom);
222 blob_appendf(&record, "U %F\n", gg.zUser);
 
 
 
223 md5sum_blob(&record, &cksum);
224 blob_appendf(&record, "Z %b\n", &cksum);
225 fast_insert_content(&record, 0, 0, 1);
226 blob_reset(&cksum);
227 }
@@ -511,10 +514,14 @@
511 }
512 zName[i] = 0;
513 }
514
515
 
 
 
 
516 /*
517 ** Read the git-fast-import format from pIn and insert the corresponding
518 ** content into the database.
519 */
520 static void git_fast_import(FILE *pIn){
@@ -534,14 +541,15 @@
534 if( strncmp(zLine, "blob", 4)==0 ){
535 gg.xFinish();
536 gg.xFinish = finish_blob;
537 }else
538 if( strncmp(zLine, "commit ", 7)==0 ){
 
539 gg.xFinish();
540 gg.xFinish = finish_commit;
541 trim_newline(&zLine[7]);
542 z = &zLine[7];
543
544 /* The argument to the "commit" line might match either of these
545 ** patterns:
546 **
547 ** (A) refs/heads/BRANCHNAME
@@ -557,15 +565,15 @@
557 ** last commit that holds that tag.
558 **
559 ** None of the above is explained in the git-fast-export
560 ** documentation. We had to figure it out via trial and error.
561 */
562 for(i=5; i<strlen(z) && z[i]!='/'; i++){}
563 gg.tagCommit = strncmp(&z[5], "tags", 4)==0; /* True for pattern B */
564 if( z[i+1]!=0 ) z += i+1;
565 if( fossil_strcmp(z, "master")==0 ) z = "trunk";
566 gg.zBranch = fossil_strdup(z);
567 gg.fromLoaded = 0;
568 }else
569 if( strncmp(zLine, "tag ", 4)==0 ){
570 gg.xFinish();
571 gg.xFinish = finish_tag;
@@ -598,12 +606,16 @@
598 gg.aData = fossil_malloc( gg.nData+1 );
599 got = fread(gg.aData, 1, gg.nData, pIn);
600 if( got!=gg.nData ){
601 fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
602 }
603 gg.aData[got] = 0;
604 if( gg.zComment==0 && gg.xFinish==finish_commit ){
 
 
 
 
605 gg.zComment = gg.aData;
606 gg.aData = 0;
607 gg.nData = 0;
608 }
609 }
@@ -616,21 +628,28 @@
616 fossil_free(gg.zMark);
617 gg.zMark = fossil_strdup(&zLine[5]);
618 }else
619 if( strncmp(zLine, "tagger ", 7)==0 || strncmp(zLine, "committer ",10)==0 ){
620 sqlite3_int64 secSince1970;
621 for(i=0; zLine[i] && zLine[i]!='<'; i++){}
622 if( zLine[i]==0 ) goto malformed_line;
623 z = &zLine[i+1];
624 for(i=i+1; zLine[i] && zLine[i]!='>'; i++){}
625 if( zLine[i]==0 ) goto malformed_line;
626 zLine[i] = 0;
627 fossil_free(gg.zUser);
628 gg.zUser = fossil_strdup(z);
 
 
 
 
 
 
 
 
629 secSince1970 = 0;
630 for(i=i+2; fossil_isdigit(zLine[i]); i++){
631 secSince1970 = secSince1970*10 + zLine[i] - '0';
632 }
633 fossil_free(gg.zDate);
634 gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970);
635 gg.zDate[10] = 'T';
636 }else
@@ -1580,12 +1599,13 @@
1580 **
1581 ** The following formats are currently understood by this command
1582 **
1583 ** --git Import from the git-fast-export file format (default)
1584 ** Options:
1585 ** --import-marks FILE Restore marks table from FILE
1586 ** --export-marks FILE Save marks table to FILE
 
1587 **
1588 ** --svn Import from the svnadmin-dump file format. The default
1589 ** behaviour (unless overridden by --flat) is to treat 3
1590 ** folders in the SVN root as special, following the
1591 ** common layout of SVN repositories. These are (by
@@ -1703,10 +1723,13 @@
1703 gsvn.revFlag = find_option("rev-tags", 0, 0)
1704 || (incrFlag && !find_option("no-rev-tags", 0, 0));
1705 }else if( gitFlag ){
1706 markfile_in = find_option("import-marks", 0, 1);
1707 markfile_out = find_option("export-marks", 0, 1);
 
 
 
1708 }
1709 verify_all_options();
1710
1711 if( g.argc!=3 && g.argc!=4 ){
1712 usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
@@ -1723,11 +1746,14 @@
1723 }
1724 db_open_repository(g.argv[2]);
1725 db_open_config(0, 0);
1726
1727 db_begin_transaction();
1728 if( !incrFlag ) db_initial_setup(0, 0, 0);
 
 
 
1729
1730 if( svnFlag ){
1731 db_multi_exec(
1732 "CREATE TEMP TABLE xrevisions("
1733 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1734
--- src/import.c
+++ src/import.c
@@ -215,13 +215,16 @@
215 static void finish_tag(void){
216 Blob record, cksum;
217 if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
218 blob_zero(&record);
219 blob_appendf(&record, "D %s\n", gg.zDate);
220 blob_appendf(&record, "T +sym-%F%F%F %s", gimport.zTagPre, gg.zTag,
221 gimport.zTagSuf, gg.zFrom);
222 if( gg.zComment ){
223 blob_appendf(&record, " %F", gg.zComment);
224 }
225 blob_appendf(&record, "\nU %F\n", gg.zUser);
226 md5sum_blob(&record, &cksum);
227 blob_appendf(&record, "Z %b\n", &cksum);
228 fast_insert_content(&record, 0, 0, 1);
229 blob_reset(&cksum);
230 }
@@ -511,10 +514,14 @@
514 }
515 zName[i] = 0;
516 }
517
518
519 static struct{
520 const char *zMasterName; /* Name of master branch */
521 } ggit;
522
523 /*
524 ** Read the git-fast-import format from pIn and insert the corresponding
525 ** content into the database.
526 */
527 static void git_fast_import(FILE *pIn){
@@ -534,14 +541,15 @@
541 if( strncmp(zLine, "blob", 4)==0 ){
542 gg.xFinish();
543 gg.xFinish = finish_blob;
544 }else
545 if( strncmp(zLine, "commit ", 7)==0 ){
546 const char *zRefName;
547 gg.xFinish();
548 gg.xFinish = finish_commit;
549 trim_newline(&zLine[7]);
550 zRefName = &zLine[7];
551
552 /* The argument to the "commit" line might match either of these
553 ** patterns:
554 **
555 ** (A) refs/heads/BRANCHNAME
@@ -557,15 +565,15 @@
565 ** last commit that holds that tag.
566 **
567 ** None of the above is explained in the git-fast-export
568 ** documentation. We had to figure it out via trial and error.
569 */
570 for(i=5; i<strlen(zRefName) && zRefName[i]!='/'; i++){}
571 gg.tagCommit = strncmp(&zRefName[5], "tags", 4)==0; /* True for pattern B */
572 if( zRefName[i+1]!=0 ) zRefName += i+1;
573 if( fossil_strcmp(zRefName, "master")==0 ) zRefName = ggit.zMasterName;
574 gg.zBranch = fossil_strdup(zRefName);
575 gg.fromLoaded = 0;
576 }else
577 if( strncmp(zLine, "tag ", 4)==0 ){
578 gg.xFinish();
579 gg.xFinish = finish_tag;
@@ -598,12 +606,16 @@
606 gg.aData = fossil_malloc( gg.nData+1 );
607 got = fread(gg.aData, 1, gg.nData, pIn);
608 if( got!=gg.nData ){
609 fossil_fatal("short read: got %d of %d bytes", got, gg.nData);
610 }
611 gg.aData[got] = '\0';
612 if( gg.zComment==0 &&
613 (gg.xFinish==finish_commit || gg.xFinish==finish_tag) ){
614 /* Strip trailing newline, it's appended to the comment. */
615 if( gg.aData[got-1] == '\n' )
616 gg.aData[got-1] = '\0';
617 gg.zComment = gg.aData;
618 gg.aData = 0;
619 gg.nData = 0;
620 }
621 }
@@ -616,21 +628,28 @@
628 fossil_free(gg.zMark);
629 gg.zMark = fossil_strdup(&zLine[5]);
630 }else
631 if( strncmp(zLine, "tagger ", 7)==0 || strncmp(zLine, "committer ",10)==0 ){
632 sqlite3_int64 secSince1970;
633 z = strchr(zLine, ' ');
634 while( fossil_isspace(*z) ) z++;
635 if( (zTo=strchr(z, '>'))==NULL ) goto malformed_line;
636 *(++zTo) = '\0';
637 /* Lookup user by contact info. */
 
638 fossil_free(gg.zUser);
639 gg.zUser = db_text(0, "SELECT login FROM user WHERE info=%Q", z);
640 if( gg.zUser==NULL ){
641 /* If there is no user with this contact info,
642 * then use the email address as the username. */
643 if ( (z=strchr(z, '<'))==NULL ) goto malformed_line;
644 z++;
645 *(zTo-1) = '\0';
646 gg.zUser = fossil_strdup(z);
647 }
648 secSince1970 = 0;
649 for(zTo++; fossil_isdigit(*zTo); zTo++){
650 secSince1970 = secSince1970*10 + *zTo - '0';
651 }
652 fossil_free(gg.zDate);
653 gg.zDate = db_text(0, "SELECT datetime(%lld, 'unixepoch')", secSince1970);
654 gg.zDate[10] = 'T';
655 }else
@@ -1580,12 +1599,13 @@
1599 **
1600 ** The following formats are currently understood by this command
1601 **
1602 ** --git Import from the git-fast-export file format (default)
1603 ** Options:
1604 ** --import-marks FILE Restore marks table from FILE
1605 ** --export-marks FILE Save marks table to FILE
1606 ** --rename-master NAME Renames the master branch to NAME
1607 **
1608 ** --svn Import from the svnadmin-dump file format. The default
1609 ** behaviour (unless overridden by --flat) is to treat 3
1610 ** folders in the SVN root as special, following the
1611 ** common layout of SVN repositories. These are (by
@@ -1703,10 +1723,13 @@
1723 gsvn.revFlag = find_option("rev-tags", 0, 0)
1724 || (incrFlag && !find_option("no-rev-tags", 0, 0));
1725 }else if( gitFlag ){
1726 markfile_in = find_option("import-marks", 0, 1);
1727 markfile_out = find_option("export-marks", 0, 1);
1728 if( !(ggit.zMasterName = find_option("rename-master", 0, 1)) ){
1729 ggit.zMasterName = "master";
1730 }
1731 }
1732 verify_all_options();
1733
1734 if( g.argc!=3 && g.argc!=4 ){
1735 usage("--git|--svn ?OPTIONS? NEW-REPOSITORY ?INPUT-FILE?");
@@ -1723,11 +1746,14 @@
1746 }
1747 db_open_repository(g.argv[2]);
1748 db_open_config(0, 0);
1749
1750 db_begin_transaction();
1751 if( !incrFlag ){
1752 db_initial_setup(0, 0, 0);
1753 db_set("main-branch", gimport.zTrunkName, 0);
1754 }
1755
1756 if( svnFlag ){
1757 db_multi_exec(
1758 "CREATE TEMP TABLE xrevisions("
1759 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1760
--- www/changes.wiki
+++ www/changes.wiki
@@ -11,11 +11,11 @@
1111
* The [/help?cmd=/tarball|/tarball] and [/help?cmd=/zip|/zip] pages
1212
now use the the r= query parameter
1313
to select which check-in to deliver. The uuid= query parameter
1414
is still accepted for backwards compatibility.
1515
* Update the built-in SQLite to version 3.18.0.
16
- * Run "[https://www.sqlite.org/pragma.html#pragma_optimize|PRAGMA optimize]"
16
+ * Run "[https://www.sqlite.org/pragma.html#pragma_optimize|PRAGMA optimize]"
1717
on the database connection as it is closing.
1818
1919
<a name='v2_1'></a>
2020
<h2>Changes for Version 2.1 (2017-03-10)</h2>
2121
2222
--- www/changes.wiki
+++ www/changes.wiki
@@ -11,11 +11,11 @@
11 * The [/help?cmd=/tarball|/tarball] and [/help?cmd=/zip|/zip] pages
12 now use the the r= query parameter
13 to select which check-in to deliver. The uuid= query parameter
14 is still accepted for backwards compatibility.
15 * Update the built-in SQLite to version 3.18.0.
16 * Run "[https://www.sqlite.org/pragma.html#pragma_optimize|PRAGMA optimize]"
17 on the database connection as it is closing.
18
19 <a name='v2_1'></a>
20 <h2>Changes for Version 2.1 (2017-03-10)</h2>
21
22
--- www/changes.wiki
+++ www/changes.wiki
@@ -11,11 +11,11 @@
11 * The [/help?cmd=/tarball|/tarball] and [/help?cmd=/zip|/zip] pages
12 now use the the r= query parameter
13 to select which check-in to deliver. The uuid= query parameter
14 is still accepted for backwards compatibility.
15 * Update the built-in SQLite to version 3.18.0.
16 * Run "[https://www.sqlite.org/pragma.html#pragma_optimize|PRAGMA optimize]"
17 on the database connection as it is closing.
18
19 <a name='v2_1'></a>
20 <h2>Changes for Version 2.1 (2017-03-10)</h2>
21
22
--- www/changes.wiki
+++ www/changes.wiki
@@ -11,11 +11,11 @@
1111
* The [/help?cmd=/tarball|/tarball] and [/help?cmd=/zip|/zip] pages
1212
now use the the r= query parameter
1313
to select which check-in to deliver. The uuid= query parameter
1414
is still accepted for backwards compatibility.
1515
* Update the built-in SQLite to version 3.18.0.
16
- * Run "[https://www.sqlite.org/pragma.html#pragma_optimize|PRAGMA optimize]"
16
+ * Run "[https://www.sqlite.org/pragma.html#pragma_optimize|PRAGMA optimize]"
1717
on the database connection as it is closing.
1818
1919
<a name='v2_1'></a>
2020
<h2>Changes for Version 2.1 (2017-03-10)</h2>
2121
2222
--- www/changes.wiki
+++ www/changes.wiki
@@ -11,11 +11,11 @@
11 * The [/help?cmd=/tarball|/tarball] and [/help?cmd=/zip|/zip] pages
12 now use the the r= query parameter
13 to select which check-in to deliver. The uuid= query parameter
14 is still accepted for backwards compatibility.
15 * Update the built-in SQLite to version 3.18.0.
16 * Run "[https://www.sqlite.org/pragma.html#pragma_optimize|PRAGMA optimize]"
17 on the database connection as it is closing.
18
19 <a name='v2_1'></a>
20 <h2>Changes for Version 2.1 (2017-03-10)</h2>
21
22
--- www/changes.wiki
+++ www/changes.wiki
@@ -11,11 +11,11 @@
11 * The [/help?cmd=/tarball|/tarball] and [/help?cmd=/zip|/zip] pages
12 now use the the r= query parameter
13 to select which check-in to deliver. The uuid= query parameter
14 is still accepted for backwards compatibility.
15 * Update the built-in SQLite to version 3.18.0.
16 * Run "[https://www.sqlite.org/pragma.html#pragma_optimize|PRAGMA optimize]"
17 on the database connection as it is closing.
18
19 <a name='v2_1'></a>
20 <h2>Changes for Version 2.1 (2017-03-10)</h2>
21
22

Keyboard Shortcuts

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