On 09/02/2017 15:06, Joerg Sonnenberger wrote:
> On Thu, Feb 09, 2017 at 01:47:43PM +, Roy Marples wrote:
>> Hi List!
>>
>> In fossil I have this: branch-1.7, tag-1.2
>> But when I export I get this: branch_1_7, tag_1_2
>>
>> Why is the name mangled like so? Surely the original names should be
>> preserved.
>
> It's currently preserving only alphanumeric characters. Noone ever
> implemented the full sanitation requirement of git.
Attached is a patch with implements sanity checking as per
https://git-scm.com/docs/git-check-ref-format
Applies with my prior patch.
Roy
Index: src/export.c
==
--- src/export.c
+++ src/export.c
@@ -161,10 +161,68 @@
printf(" %s <%s>", zName, zEmail);
free(zName);
free(zEmail);
db_reset();
}
+
+#define REFREPLACEMENT '_'
+
+/*
+** Output a sanitized git named reference.
+** https://git-scm.com/docs/git-check-ref-format
+** This implementation assumes we are only printing
+** the branch or tag part of the reference.
+*/
+static void print_ref(const char *zRef){
+ char *zEncoded = mprintf("%s", zRef);
+ int i, w;
+ if (zEncoded[0]=='@' && zEncoded[1]=='\0'){
+putchar(REFREPLACEMENT);
+return;
+ }
+ for(i=0, w=0; zEncoded[i]; i++, w++){
+if( i!=0 ){ /* Two letter tests */
+ if( (zEncoded[i-1]=='.' && zEncoded[i]=='.') ||
+ (zEncoded[i-1]=='@' && zEncoded[i]=='{') ){
+zEncoded[w]=zEncoded[w-1]=REFREPLACEMENT;
+continue;
+ }
+ if( zEncoded[i-1]=='/' && zEncoded[i]=='/' ){
+w--; /* Normalise to a single / by rolling back w */
+continue;
+ }
+}
+/* No control characters */
+if( (unsigned)zEncoded[i]<0x20 || zEncoded[i]==0x7f ){
+ zEncoded[w]=REFREPLACEMENT;
+ continue;
+}
+switch( zEncoded[i] ){
+ case ' ':
+ case '^':
+ case ':':
+ case '?':
+ case '*':
+ case '[':
+ case '\\':
+zEncoded[w]=REFREPLACEMENT;
+ break;
+}
+ }
+ /* Cannot begin with a . or / */
+ if( zEncoded[0]=='.' || zEncoded[0] == '/' ) zEncoded[0]=REFREPLACEMENT;
+ if( i>0 ){
+i--; w--;
+/* Or end with a . or / */
+if( zEncoded[i]=='.' || zEncoded[i] == '/' ) zEncoded[w]=REFREPLACEMENT;
+/* Cannot end with .lock */
+if ( i>4 && strcmp((zEncoded+i)-5, ".lock")==0 )
+ memset((zEncoded+w)-5, REFREPLACEMENT, 5);
+ }
+ printf("%s", zEncoded);
+ free(zEncoded);
+}
#define BLOBMARK(rid) ((rid) * 2)
#define COMMITMARK(rid) ((rid) * 2 + 1)
/*
@@ -547,26 +605,22 @@
const char *zSecondsSince1970 = db_column_text(, 0);
int ckinId = db_column_int(, 1);
const char *zComment = db_column_text(, 2);
const char *zUser = db_column_text(, 3);
const char *zBranch = db_column_text(, 4);
-char *zBr;
char *zMark;
bag_insert(, ckinId);
db_bind_int(, ":rid", ckinId);
db_step();
db_reset();
if( zBranch==0 ) zBranch = "trunk";
-zBr = mprintf("%s", zBranch);
-for(i=0; zBr[i]; i++){
- if( !fossil_isalnum(zBr[i]) ) zBr[i] = '_';
-}
zMark = mark_name_from_rid(ckinId, _mark);
-printf("commit refs/heads/%s\nmark %s\n", zBr, zMark);
+printf("commit refs/heads/");
+print_ref(zBranch);
+printf("\nmark %s\n", zMark);
free(zMark);
-free(zBr);
printf("committer");
print_person(zUser);
printf(" %s +\n", zSecondsSince1970);
if( zComment==0 ) zComment = "null comment";
printf("data %d\n%s\n", (int)strlen(zComment), zComment);
@@ -637,30 +691,24 @@
" FROM tagxref JOIN tag USING(tagid)"
" WHERE tagtype=1 AND tagname GLOB 'sym-*'"
);
while( db_step()==SQLITE_ROW ){
const char *zTagname = db_column_text(, 0);
-char *zEncoded = 0;
int rid = db_column_int(, 1);
char *zMark = mark_name_from_rid(rid, _mark);
const char *zSecSince1970 = db_column_text(, 2);
const char *zUser = db_column_text(, 3);
-int i;
if( rid==0 || !bag_find(, rid) ) continue;
zTagname += 4;
-zEncoded = mprintf("%s", zTagname);
-for(i=0; zEncoded[i]; i++){
- if( !fossil_isalnum(zEncoded[i]) ) zEncoded[i] = '_';
-}
-printf("tag %s\n", zEncoded);
-printf("from %s\n", zMark);
+printf("tag ");
+print_ref(zTagname);
+printf("\nfrom %s\n", zMark);
free(zMark);
printf("tagger");
print_person(zUser);
printf(" %s +\n", zSecSince1970);
printf("data 0\n");
-fossil_free(zEncoded);
}
db_finalize();
if( markfile_out!=0 ){
FILE *f;
___
fossil-users mailing list
fossil-users@lists.fossil-scm.org
http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users