On 09/02/2017 15:06, Joerg Sonnenberger wrote:
> On Thu, Feb 09, 2017 at 01:47:43PM +0000, 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(&q);
 }
+
+#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(&q, 0);
     int ckinId = db_column_int(&q, 1);
     const char *zComment = db_column_text(&q, 2);
     const char *zUser = db_column_text(&q, 3);
     const char *zBranch = db_column_text(&q, 4);
-    char *zBr;
     char *zMark;
 
     bag_insert(&vers, ckinId);
     db_bind_int(&q2, ":rid", ckinId);
     db_step(&q2);
     db_reset(&q2);
     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, &unused_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 +0000\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(&q)==SQLITE_ROW ){
     const char *zTagname = db_column_text(&q, 0);
-    char *zEncoded = 0;
     int rid = db_column_int(&q, 1);
     char *zMark = mark_name_from_rid(rid, &unused_mark);
     const char *zSecSince1970 = db_column_text(&q, 2);
     const char *zUser = db_column_text(&q, 3);
-    int i;
     if( rid==0 || !bag_find(&vers, 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 +0000\n", zSecSince1970);
     printf("data 0\n");
-    fossil_free(zEncoded);
   }
   db_finalize(&q);
 
   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

Reply via email to