Fossil

Check-in [bf56b2dd]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Cleanup of the code used to resolve tag names in contexts where an artifact ID can be entered.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:bf56b2ddf4082e7ba0654574f7cd60f6246c54b3
User & Date: drh 2010-01-19 17:34:45
References
2010-01-20
15:50 Fixed ticket [a5403e6e]: Clicking on ticket link on Timeline page redirects to Index Page. plus 2 other changes artifact: 74eada78 user: drh
Context
2010-01-19
18:28
Add the "pullonly" option to the "autosync" setting. check-in: ea27129c user: drh tags: trunk
18:16
Pull in all the latest changes from the trunk as of 2010-01-19. check-in: b8df912e user: drh tags: ssl
18:11
Start a new branch that strives to contain only code for which we hold clear title. check-in: ab0a0d76 user: drh tags: clear-title
17:34
Cleanup of the code used to resolve tag names in contexts where an artifact ID can be entered. check-in: bf56b2dd user: drh tags: trunk
14:15
Show the edited user id in annotations. check-in: e7efca9e user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/info.c.

1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083

1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
** a ticket changes or a wiki editor or something else. 
**
** Figure out what the artifact ID is and jump to it.
*/
void info_page(void){
  const char *zName;
  Blob uuid;
  int rid, nName;
  
  zName = P("name");
  if( zName==0 ) fossil_redirect_home();
  nName = strlen(zName);
  if( nName<4 || nName>UUID_SIZE || !validate16(zName, nName) ){
    switch( sym_tag_to_uuid(zName, &uuid) ){
      case 1: {
        /* got one UUID, use it */
        zName = blob_str(&uuid);
        break;
      }
      case 2: {
        /* go somewhere to show the multiple UUIDs */
        return;
        break;
      }
      default: {
        fossil_redirect_home();
        break;
      }
    }
  }

  if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid GLOB '%s*'", zName) ){
    tktview_page();
    return;
  }
  rid = db_int(0, "SELECT rid FROM blob WHERE uuid GLOB '%s*'", zName);
  if( rid==0 ){
    style_header("Broken Link");
    @ <p>No such object: %h(zName)</p>
    style_footer();
    return;
  }
  if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){







|



|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
>
|



|







1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066












1067

1068


1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
** a ticket changes or a wiki editor or something else. 
**
** Figure out what the artifact ID is and jump to it.
*/
void info_page(void){
  const char *zName;
  Blob uuid;
  int rid;
  
  zName = P("name");
  if( zName==0 ) fossil_redirect_home();
  blob_set(&uuid, zName);
  if( name_to_uuid(&uuid, 1) ){












    fossil_redirect_home();

  }


  zName = blob_str(&uuid);
  if( db_exists("SELECT 1 FROM ticket WHERE tkt_uuid='%s'", zName) ){
    tktview_page();
    return;
  }
  rid = db_int(0, "SELECT rid FROM blob WHERE uuid='%s'", zName);
  if( rid==0 ){
    style_header("Broken Link");
    @ <p>No such object: %h(zName)</p>
    style_footer();
    return;
  }
  if( db_exists("SELECT 1 FROM mlink WHERE mid=%d", rid) ){

Changes to src/name.c.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88







89
90
91

92
93
94
95
96
97
98
99
100
101
102
103
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122




123
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

/*
** This routine takes a user-entered UUID which might be in mixed
** case and might only be a prefix of the full UUID and converts it
** into the full-length UUID in canonical form.
**
** If the input is not a UUID or a UUID prefix, then try to resolve
** the name as a tag.
**
** Return the number of errors.
*/
int name_to_uuid(Blob *pName, int iErrPriority){
  int rc;
  int sz;
  sz = blob_size(pName);
  if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){
    Blob uuid;
    static const char prefix[] = "tag:";
    static const int preflen = sizeof(prefix)-1;
    const char *zName = blob_str(pName);

    if( strncmp(zName, prefix, preflen)==0 ){
      zName += preflen;
    }

    sym_tag_to_uuid(zName, &uuid);
    if( blob_size(&uuid)==0 ){
      fossil_error(iErrPriority, "not a valid object name: %s", zName);
      blob_reset(&uuid);
      return 1;
    }else{
      blob_reset(pName);
      *pName = uuid;
      return 0;
    }
  }
  blob_materialize(pName);
  canonical16(blob_buffer(pName), sz);
  if( sz==UUID_SIZE ){
    rc = db_int(1, "SELECT 0 FROM blob WHERE uuid=%B", pName);
    if( rc ){
      fossil_error(iErrPriority, "no such artifact: %b", pName);
      blob_reset(pName);
    }
  }else if( sz<UUID_SIZE && sz>=4 ){
    Stmt q;
    char zOrig[UUID_SIZE+1];
    memcpy(zOrig, blob_buffer(pName), sz);
    zOrig[sz] = 0;
    blob_reset(pName);
    db_prepare(&q, "SELECT uuid FROM blob"
                   " WHERE uuid>='%s'"
                   "   AND substr(uuid,1,%d)='%s'",
                   zOrig, sz, zOrig);
    if( db_step(&q)!=SQLITE_ROW ){

      db_finalize(&q);







      fossil_error(iErrPriority, "no artifacts match the prefix \"%s\"", zOrig);
      return 1;
    }

    blob_append(pName, db_column_text(&q, 0), db_column_bytes(&q, 0));
    if( db_step(&q)==SQLITE_ROW ){
      fossil_error(iErrPriority, 
         "multiple artifacts match the prefix \"%s\"",
         zOrig
      );
      blob_reset(pName);
      db_finalize(&q);
      return 1;
    }
    db_finalize(&q);
    rc = 0;
................................................................................
  }else{
    rc = 0;
  }
  return rc;
}

/*
** This routine takes a name which might be a tag and attempts to
** produce a UUID. The UUID (if any) is returned in the blob pointed
** to by the second argument.
**
** Return as follows:
**      0   Name is not a tag
**      1   A single UUID was found
**      2   More than one UUID was found, so this is presumably a
**          propagating tag. The return UUID is the most recent,
**          which is most likely to be the one wanted.
*/
int tag_to_uuid(const char *pName, Blob *pUuid,const char *pPrefix){




  Stmt q;
  int count = 0;
  db_prepare(&q,
    "SELECT (SELECT uuid FROM blob WHERE rid=objid)"
    "  FROM tagxref JOIN event ON rid=objid"
    " WHERE tagxref.tagid=(SELECT tagid FROM tag WHERE tagname=%Q||%Q)"
    "   AND tagtype>0"
    "   AND value IS NULL"
    " ORDER BY event.mtime DESC",
    pPrefix,
    pName

  );
  blob_zero(pUuid);
  while( db_step(&q)==SQLITE_ROW ){
    count++;
    if(count>1){
      break;
    }
    db_column_blob(&q, 0, pUuid);
  }
  db_finalize(&q);
  return count;
}

/*
** This routine takes a name which might be a symbolic tag and
** attempts to produce a UUID. See tag_to_uuid.
*/
int sym_tag_to_uuid(const char *pName, Blob *pUuid){
    return tag_to_uuid(pName,pUuid,"sym-");
}

/*
** COMMAND:  test-name-to-id
**
** Convert a name to a full artifact ID.
*/







|








|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<











<
<
<
<
|
<
<
<

>

>
>
>
>
>
>
>
|


>



|
<







 







|
|
|

|
|
<
<
<
<

|
>
>
>
>
|
|
|
|
<
<
<
<
|
<
<
>
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62





63
64
65
66
67
68
69
70
71
72
73




74



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
...
100
101
102
103
104
105
106
107
108
109
110
111
112




113
114
115
116
117
118
119
120
121
122




123


124
125









126








127
128
129
130
131
132
133

/*
** This routine takes a user-entered UUID which might be in mixed
** case and might only be a prefix of the full UUID and converts it
** into the full-length UUID in canonical form.
**
** If the input is not a UUID or a UUID prefix, then try to resolve
** the name as a tag.  If multiple tags match, pick the latest.
**
** Return the number of errors.
*/
int name_to_uuid(Blob *pName, int iErrPriority){
  int rc;
  int sz;
  sz = blob_size(pName);
  if( sz>UUID_SIZE || sz<4 || !validate16(blob_buffer(pName), sz) ){
    char *zUuid;
    const char *zName = blob_str(pName);
    if( memcmp(zName, "tag:", 4)==0 ){
      zName += 4;
    }
    zUuid = tag_to_uuid(zName);
    if( zUuid ){
      blob_reset(pName);
      blob_append(pName, zUuid, -1);
      free(zUuid);
      return 0;
    }
    fossil_error(iErrPriority, "not a valid object name: %s", zName);
    return 1;





  }
  blob_materialize(pName);
  canonical16(blob_buffer(pName), sz);
  if( sz==UUID_SIZE ){
    rc = db_int(1, "SELECT 0 FROM blob WHERE uuid=%B", pName);
    if( rc ){
      fossil_error(iErrPriority, "no such artifact: %b", pName);
      blob_reset(pName);
    }
  }else if( sz<UUID_SIZE && sz>=4 ){
    Stmt q;




    db_prepare(&q, "SELECT uuid FROM blob WHERE uuid GLOB '%b*'", pName);



    if( db_step(&q)!=SQLITE_ROW ){
      char *zUuid;
      db_finalize(&q);
      zUuid = tag_to_uuid(blob_str(pName));
      if( zUuid ){
        blob_reset(pName);
        blob_append(pName, zUuid, -1);
        free(zUuid);
        return 0;
      }
      fossil_error(iErrPriority, "no artifacts match the prefix \"%b\"", pName);
      return 1;
    }
    blob_reset(pName);
    blob_append(pName, db_column_text(&q, 0), db_column_bytes(&q, 0));
    if( db_step(&q)==SQLITE_ROW ){
      fossil_error(iErrPriority, 
         "multiple artifacts match"

      );
      blob_reset(pName);
      db_finalize(&q);
      return 1;
    }
    db_finalize(&q);
    rc = 0;
................................................................................
  }else{
    rc = 0;
  }
  return rc;
}

/*
** Convert a symbolic tag name into the UUID of a check-in that contains
** that tag.  If the tag appears on multiple check-ins, return the UUID
** of the most recent check-in with the tag.
**
** Memory to hold the returned string comes from malloc() and needs to
** be freed by the caller.




*/
char *tag_to_uuid(const char *zTag){
  char *zUuid = 
    db_text(0,
       "SELECT blob.uuid"
       "  FROM tag, tagxref, event, blob"
       " WHERE tag.tagname='sym-'||%Q "
       "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
       "   AND event.objid=tagxref.rid "
       "   AND blob.rid=event.objid "




       " ORDER BY event.mtime DESC ",


       zTag
    );









  return zUuid;








}

/*
** COMMAND:  test-name-to-id
**
** Convert a name to a full artifact ID.
*/