Fossil SCM

Add function print_ref to sanitize branch and tag names in accordance with https://git-scm.com/docs/git-check-ref-format Use this rather than simply replacing non alpha or numeric chars for branch and tag names when exporting.

roy.marples 2017-02-10 01:25 UTC roy-export
Commit abc87ccdd5aac7b952a8121ab46c715a52900e5f
1 file changed +64 -16
+64 -16
--- src/export.c
+++ src/export.c
@@ -161,10 +161,68 @@
161161
printf(" %s <%s>", zName, zEmail);
162162
free(zName);
163163
free(zEmail);
164164
db_reset(&q);
165165
}
166
+
167
+#define REFREPLACEMENT '_'
168
+
169
+/*
170
+** Output a sanitized git named reference.
171
+** https://git-scm.com/docs/git-check-ref-format
172
+** This implementation assumes we are only printing
173
+** the branch or tag part of the reference.
174
+*/
175
+static void print_ref(const char *zRef){
176
+ char *zEncoded = mprintf("%s", zRef);
177
+ int i, w;
178
+ if (zEncoded[0]=='@' && zEncoded[1]=='\0'){
179
+ putchar(REFREPLACEMENT);
180
+ return;
181
+ }
182
+ for(i=0, w=0; zEncoded[i]; i++, w++){
183
+ if( i!=0 ){ /* Two letter tests */
184
+ if( (zEncoded[i-1]=='.' && zEncoded[i]=='.') ||
185
+ (zEncoded[i-1]=='@' && zEncoded[i]=='{') ){
186
+ zEncoded[w]=zEncoded[w-1]=REFREPLACEMENT;
187
+ continue;
188
+ }
189
+ if( zEncoded[i-1]=='/' && zEncoded[i]=='/' ){
190
+ w--; /* Normalise to a single / by rolling back w */
191
+ continue;
192
+ }
193
+ }
194
+ /* No control characters */
195
+ if( (unsigned)zEncoded[i]<0x20 || zEncoded[i]==0x7f ){
196
+ zEncoded[w]=REFREPLACEMENT;
197
+ continue;
198
+ }
199
+ switch( zEncoded[i] ){
200
+ case ' ':
201
+ case '^':
202
+ case ':':
203
+ case '?':
204
+ case '*':
205
+ case '[':
206
+ case '\\':
207
+ zEncoded[w]=REFREPLACEMENT;
208
+ break;
209
+ }
210
+ }
211
+ /* Cannot begin with a . or / */
212
+ if( zEncoded[0]=='.' || zEncoded[0] == '/' ) zEncoded[0]=REFREPLACEMENT;
213
+ if( i>0 ){
214
+ i--; w--;
215
+ /* Or end with a . or / */
216
+ if( zEncoded[i]=='.' || zEncoded[i] == '/' ) zEncoded[w]=REFREPLACEMENT;
217
+ /* Cannot end with .lock */
218
+ if ( i>4 && strcmp((zEncoded+i)-5, ".lock")==0 )
219
+ memset((zEncoded+w)-5, REFREPLACEMENT, 5);
220
+ }
221
+ printf("%s", zEncoded);
222
+ free(zEncoded);
223
+}
166224
167225
#define BLOBMARK(rid) ((rid) * 2)
168226
#define COMMITMARK(rid) ((rid) * 2 + 1)
169227
170228
/*
@@ -547,26 +605,22 @@
547605
const char *zSecondsSince1970 = db_column_text(&q, 0);
548606
int ckinId = db_column_int(&q, 1);
549607
const char *zComment = db_column_text(&q, 2);
550608
const char *zUser = db_column_text(&q, 3);
551609
const char *zBranch = db_column_text(&q, 4);
552
- char *zBr;
553610
char *zMark;
554611
555612
bag_insert(&vers, ckinId);
556613
db_bind_int(&q2, ":rid", ckinId);
557614
db_step(&q2);
558615
db_reset(&q2);
559616
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
- }
564617
zMark = mark_name_from_rid(ckinId, &unused_mark);
565
- printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
618
+ printf("commit refs/heads/");
619
+ print_ref(zBranch);
620
+ printf("\nmark %s\n", zMark);
566621
free(zMark);
567
- free(zBr);
568622
printf("committer");
569623
print_person(zUser);
570624
printf(" %s +0000\n", zSecondsSince1970);
571625
if( zComment==0 ) zComment = "null comment";
572626
printf("data %d\n%s\n", (int)strlen(zComment), zComment);
@@ -637,30 +691,24 @@
637691
" FROM tagxref JOIN tag USING(tagid)"
638692
" WHERE tagtype=1 AND tagname GLOB 'sym-*'"
639693
);
640694
while( db_step(&q)==SQLITE_ROW ){
641695
const char *zTagname = db_column_text(&q, 0);
642
- char *zEncoded = 0;
643696
int rid = db_column_int(&q, 1);
644697
char *zMark = mark_name_from_rid(rid, &unused_mark);
645698
const char *zSecSince1970 = db_column_text(&q, 2);
646699
const char *zUser = db_column_text(&q, 3);
647
- int i;
648700
if( rid==0 || !bag_find(&vers, rid) ) continue;
649701
zTagname += 4;
650
- zEncoded = mprintf("%s", zTagname);
651
- for(i=0; zEncoded[i]; i++){
652
- if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
653
- }
654
- printf("tag %s\n", zEncoded);
655
- printf("from %s\n", zMark);
702
+ printf("tag ");
703
+ print_ref(zTagname);
704
+ printf("\nfrom %s\n", zMark);
656705
free(zMark);
657706
printf("tagger");
658707
print_person(zUser);
659708
printf(" %s +0000\n", zSecSince1970);
660709
printf("data 0\n");
661
- fossil_free(zEncoded);
662710
}
663711
db_finalize(&q);
664712
665713
if( markfile_out!=0 ){
666714
FILE *f;
667715
--- src/export.c
+++ src/export.c
@@ -161,10 +161,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 /*
@@ -547,26 +605,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);
@@ -637,30 +691,24 @@
637 " FROM tagxref JOIN tag USING(tagid)"
638 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
639 );
640 while( db_step(&q)==SQLITE_ROW ){
641 const char *zTagname = db_column_text(&q, 0);
642 char *zEncoded = 0;
643 int rid = db_column_int(&q, 1);
644 char *zMark = mark_name_from_rid(rid, &unused_mark);
645 const char *zSecSince1970 = db_column_text(&q, 2);
646 const char *zUser = db_column_text(&q, 3);
647 int i;
648 if( rid==0 || !bag_find(&vers, rid) ) continue;
649 zTagname += 4;
650 zEncoded = mprintf("%s", zTagname);
651 for(i=0; zEncoded[i]; i++){
652 if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
653 }
654 printf("tag %s\n", zEncoded);
655 printf("from %s\n", zMark);
656 free(zMark);
657 printf("tagger");
658 print_person(zUser);
659 printf(" %s +0000\n", zSecSince1970);
660 printf("data 0\n");
661 fossil_free(zEncoded);
662 }
663 db_finalize(&q);
664
665 if( markfile_out!=0 ){
666 FILE *f;
667
--- src/export.c
+++ src/export.c
@@ -161,10 +161,68 @@
161 printf(" %s <%s>", zName, zEmail);
162 free(zName);
163 free(zEmail);
164 db_reset(&q);
165 }
166
167 #define REFREPLACEMENT '_'
168
169 /*
170 ** Output a sanitized git named reference.
171 ** https://git-scm.com/docs/git-check-ref-format
172 ** This implementation assumes we are only printing
173 ** the branch or tag part of the reference.
174 */
175 static void print_ref(const char *zRef){
176 char *zEncoded = mprintf("%s", zRef);
177 int i, w;
178 if (zEncoded[0]=='@' && zEncoded[1]=='\0'){
179 putchar(REFREPLACEMENT);
180 return;
181 }
182 for(i=0, w=0; zEncoded[i]; i++, w++){
183 if( i!=0 ){ /* Two letter tests */
184 if( (zEncoded[i-1]=='.' && zEncoded[i]=='.') ||
185 (zEncoded[i-1]=='@' && zEncoded[i]=='{') ){
186 zEncoded[w]=zEncoded[w-1]=REFREPLACEMENT;
187 continue;
188 }
189 if( zEncoded[i-1]=='/' && zEncoded[i]=='/' ){
190 w--; /* Normalise to a single / by rolling back w */
191 continue;
192 }
193 }
194 /* No control characters */
195 if( (unsigned)zEncoded[i]<0x20 || zEncoded[i]==0x7f ){
196 zEncoded[w]=REFREPLACEMENT;
197 continue;
198 }
199 switch( zEncoded[i] ){
200 case ' ':
201 case '^':
202 case ':':
203 case '?':
204 case '*':
205 case '[':
206 case '\\':
207 zEncoded[w]=REFREPLACEMENT;
208 break;
209 }
210 }
211 /* Cannot begin with a . or / */
212 if( zEncoded[0]=='.' || zEncoded[0] == '/' ) zEncoded[0]=REFREPLACEMENT;
213 if( i>0 ){
214 i--; w--;
215 /* Or end with a . or / */
216 if( zEncoded[i]=='.' || zEncoded[i] == '/' ) zEncoded[w]=REFREPLACEMENT;
217 /* Cannot end with .lock */
218 if ( i>4 && strcmp((zEncoded+i)-5, ".lock")==0 )
219 memset((zEncoded+w)-5, REFREPLACEMENT, 5);
220 }
221 printf("%s", zEncoded);
222 free(zEncoded);
223 }
224
225 #define BLOBMARK(rid) ((rid) * 2)
226 #define COMMITMARK(rid) ((rid) * 2 + 1)
227
228 /*
@@ -547,26 +605,22 @@
605 const char *zSecondsSince1970 = db_column_text(&q, 0);
606 int ckinId = db_column_int(&q, 1);
607 const char *zComment = db_column_text(&q, 2);
608 const char *zUser = db_column_text(&q, 3);
609 const char *zBranch = db_column_text(&q, 4);
 
610 char *zMark;
611
612 bag_insert(&vers, ckinId);
613 db_bind_int(&q2, ":rid", ckinId);
614 db_step(&q2);
615 db_reset(&q2);
616 if( zBranch==0 ) zBranch = "trunk";
 
 
 
 
617 zMark = mark_name_from_rid(ckinId, &unused_mark);
618 printf("commit refs/heads/");
619 print_ref(zBranch);
620 printf("\nmark %s\n", zMark);
621 free(zMark);
 
622 printf("committer");
623 print_person(zUser);
624 printf(" %s +0000\n", zSecondsSince1970);
625 if( zComment==0 ) zComment = "null comment";
626 printf("data %d\n%s\n", (int)strlen(zComment), zComment);
@@ -637,30 +691,24 @@
691 " FROM tagxref JOIN tag USING(tagid)"
692 " WHERE tagtype=1 AND tagname GLOB 'sym-*'"
693 );
694 while( db_step(&q)==SQLITE_ROW ){
695 const char *zTagname = db_column_text(&q, 0);
 
696 int rid = db_column_int(&q, 1);
697 char *zMark = mark_name_from_rid(rid, &unused_mark);
698 const char *zSecSince1970 = db_column_text(&q, 2);
699 const char *zUser = db_column_text(&q, 3);
 
700 if( rid==0 || !bag_find(&vers, rid) ) continue;
701 zTagname += 4;
702 printf("tag ");
703 print_ref(zTagname);
704 printf("\nfrom %s\n", zMark);
 
 
 
705 free(zMark);
706 printf("tagger");
707 print_person(zUser);
708 printf(" %s +0000\n", zSecSince1970);
709 printf("data 0\n");
 
710 }
711 db_finalize(&q);
712
713 if( markfile_out!=0 ){
714 FILE *f;
715

Keyboard Shortcuts

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