Fossil

Check-in [2a013f0228]
Login

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

Overview
Comment:In contexts where only a check-out makes since, only resolve tags or branch names into check-outs, not events or other artifacts. Ticket [5f611295e3c2a8].
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2a013f02282f36c9f53343534634d30b9f281dc4
User & Date: drh 2011-06-01 22:32:29.319
Context
2011-06-01
22:39
Add the --type option to the "fossil tag find" command. Ticket [9bed1f604e0773] ... (check-in: d5b9674ec5 user: drh tags: trunk)
22:32
In contexts where only a check-out makes since, only resolve tags or branch names into check-outs, not events or other artifacts. Ticket [5f611295e3c2a8]. ... (check-in: 2a013f0228 user: drh tags: trunk)
2011-05-31
12:52
Always use the alternate-form flag "#" to control the number of input bytes to printf conversions like %t, %h, and %q. Do not use precision in those cases since precision limits the number of output characters, not the number of input characters. Ticket [8967ea1df4f51af]. ... (check-in: e5e6ca4659 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/bisect.c.
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
160
161
162
163
164
165
166
  n = strlen(zCmd);
  if( n==0 ) zCmd = "-";
  if( memcmp(zCmd, "bad", n)==0 ){
    int ridBad;
    if( g.argc==3 ){
      ridBad = db_lget_int("checkout",0);
    }else{
      ridBad = name_to_rid(g.argv[3]);
    }
    db_lset_int("bisect-bad", ridBad);
    if( ridBad>0
     && bisect_option("auto-next")
     && db_lget_int("bisect-good",0)>0
    ){
      zCmd = "next";
      n = 4;
    }else{
      return;
    }
  }else if( memcmp(zCmd, "good", n)==0 ){
    int ridGood;
    if( g.argc==3 ){
      ridGood = db_lget_int("checkout",0);
    }else{
      ridGood = name_to_rid(g.argv[3]);
    }
    db_lset_int("bisect-good", ridGood);
    if( ridGood>0
     && bisect_option("auto-next")
     && db_lget_int("bisect-bad",0)>0
    ){
      zCmd = "next";







|
















|







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
160
161
162
163
164
165
166
  n = strlen(zCmd);
  if( n==0 ) zCmd = "-";
  if( memcmp(zCmd, "bad", n)==0 ){
    int ridBad;
    if( g.argc==3 ){
      ridBad = db_lget_int("checkout",0);
    }else{
      ridBad = name_to_typed_rid(g.argv[3], "ci");
    }
    db_lset_int("bisect-bad", ridBad);
    if( ridBad>0
     && bisect_option("auto-next")
     && db_lget_int("bisect-good",0)>0
    ){
      zCmd = "next";
      n = 4;
    }else{
      return;
    }
  }else if( memcmp(zCmd, "good", n)==0 ){
    int ridGood;
    if( g.argc==3 ){
      ridGood = db_lget_int("checkout",0);
    }else{
      ridGood = name_to_typed_rid(g.argv[3], "ci");
    }
    db_lset_int("bisect-good", ridGood);
    if( ridGood>0
     && bisect_option("auto-next")
     && db_lget_int("bisect-bad",0)>0
    ){
      zCmd = "next";
Changes to src/branch.c.
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
        "   AND tagid=(SELECT tagid FROM tag WHERE tagname='sym-%s')",
        zBranch)!=0 ){
    fossil_fatal("branch \"%s\" already exists", zBranch);
  }

  user_select();
  db_begin_transaction();
  rootid = name_to_rid(g.argv[4]);
  if( rootid==0 ){
    fossil_fatal("unable to locate check-in off of which to branch");
  }

  pParent = manifest_get(rootid, CFTYPE_MANIFEST);
  if( pParent==0 ){
    fossil_fatal("%s is not a valid check-in", g.argv[4]);







|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
        "   AND tagid=(SELECT tagid FROM tag WHERE tagname='sym-%s')",
        zBranch)!=0 ){
    fossil_fatal("branch \"%s\" already exists", zBranch);
  }

  user_select();
  db_begin_transaction();
  rootid = name_to_typed_rid(g.argv[4], "ci");
  if( rootid==0 ){
    fossil_fatal("unable to locate check-in off of which to branch");
  }

  pParent = manifest_get(rootid, CFTYPE_MANIFEST);
  if( pParent==0 ){
    fossil_fatal("%s is not a valid check-in", g.argv[4]);
Changes to src/checkout.c.
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
** If anything goes wrong, panic.
*/
int load_vfile(const char *zName){
  Blob uuid;
  int vid;

  blob_init(&uuid, zName, -1);
  if( name_to_uuid(&uuid, 1) ){
    fossil_panic(g.zErrMsg);
  }
  vid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
  if( vid==0 ){
    fossil_fatal("no such check-in: %s", g.argv[2]);
  }
  if( !is_a_version(vid) ){







|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
** If anything goes wrong, panic.
*/
int load_vfile(const char *zName){
  Blob uuid;
  int vid;

  blob_init(&uuid, zName, -1);
  if( name_to_uuid(&uuid, 1, "ci") ){
    fossil_panic(g.zErrMsg);
  }
  vid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
  if( vid==0 ){
    fossil_fatal("no such check-in: %s", g.argv[2]);
  }
  if( !is_a_version(vid) ){
Changes to src/descendants.c.
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  Stmt q;
  int base;

  db_must_be_within_tree();
  if( g.argc==2 ){
    base = db_lget_int("checkout", 0);
  }else{
    base = name_to_rid(g.argv[2]);
  }
  if( base==0 ) return;
  compute_leaves(base, 0);
  db_prepare(&q,
    "%s"
    "   AND event.objid IN (SELECT rid FROM leaves)"
    " ORDER BY event.mtime DESC",







|







240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  Stmt q;
  int base;

  db_must_be_within_tree();
  if( g.argc==2 ){
    base = db_lget_int("checkout", 0);
  }else{
    base = name_to_typed_rid(g.argv[2], "ci");
  }
  if( base==0 ) return;
  compute_leaves(base, 0);
  db_prepare(&q,
    "%s"
    "   AND event.objid IN (SELECT rid FROM leaves)"
    " ORDER BY event.mtime DESC",
Changes to src/diff.c.
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
  int i;
  int iLimit;
  int annFlags = 0;
  Annotator ann;

  login_check_credentials();
  if( !g.okRead ){ login_needed(); return; }
  mid = name_to_rid(PD("checkin","0"));
  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
  if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
  iLimit = atoi(PD("limit","-1"));
  if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
    fossil_redirect_home();
  }
  style_header("File Annotation");







|







835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
  int i;
  int iLimit;
  int annFlags = 0;
  Annotator ann;

  login_check_credentials();
  if( !g.okRead ){ login_needed(); return; }
  mid = name_to_typed_rid(PD("checkin","0"),"ci");
  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
  if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
  iLimit = atoi(PD("limit","-1"));
  if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
    fossil_redirect_home();
  }
  style_header("File Annotation");
Changes to src/diffcmd.c.
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0;
  asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 1, 0);
  blob_zero(&sql);
  db_begin_transaction();
  if( zFrom ){
    int rid = name_to_rid(zFrom);
    if( !is_a_version(rid) ){
      fossil_fatal("no such check-in: %s", zFrom);
    }
    load_vfile_from_rid(rid);
    blob_appendf(&sql,
      "SELECT v2.pathname, v2.deleted, v2.chnged, v2.rid==0, v1.rid"
      "  FROM vfile v1, vfile v2 "







|







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  ignoreEolWs = (diffFlags & DIFF_NOEOLWS)!=0;
  asNewFile = (diffFlags & DIFF_NEWFILE)!=0;
  vid = db_lget_int("checkout", 0);
  vfile_check_signature(vid, 1, 0);
  blob_zero(&sql);
  db_begin_transaction();
  if( zFrom ){
    int rid = name_to_typed_rid(zFrom, "ci");
    if( !is_a_version(rid) ){
      fossil_fatal("no such check-in: %s", zFrom);
    }
    load_vfile_from_rid(rid);
    blob_appendf(&sql,
      "SELECT v2.pathname, v2.deleted, v2.chnged, v2.rid==0, v1.rid"
      "  FROM vfile v1, vfile v2 "
Changes to src/doc.c.
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
    }
  }else{
    db_begin_transaction();
    if( fossil_strcmp(zBaseline,"tip")==0 ){
      vid = db_int(0, "SELECT objid FROM event WHERE type='ci'"
                      " ORDER BY mtime DESC LIMIT 1");
    }else{
      vid = name_to_rid(zBaseline);
    }

    /* Create the baseline cache if it does not already exist */
    db_multi_exec(
      "CREATE TABLE IF NOT EXISTS vcache(\n"
      "  vid INTEGER,         -- baseline ID\n"
      "  fname TEXT,          -- filename\n"







|







394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
    }
  }else{
    db_begin_transaction();
    if( fossil_strcmp(zBaseline,"tip")==0 ){
      vid = db_int(0, "SELECT objid FROM event WHERE type='ci'"
                      " ORDER BY mtime DESC LIMIT 1");
    }else{
      vid = name_to_typed_rid(zBaseline, "ci");
    }

    /* Create the baseline cache if it does not already exist */
    db_multi_exec(
      "CREATE TABLE IF NOT EXISTS vcache(\n"
      "  vid INTEGER,         -- baseline ID\n"
      "  fname TEXT,          -- filename\n"
Changes to src/info.c.
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
    }
    if( db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'event-%q*'", zName) ){
      event_page();
      return;
    }
  }
  blob_set(&uuid, zName);
  rc = name_to_uuid(&uuid, -1);
  if( rc==1 ){
    style_header("No Such Object");
    @ <p>No such object: %h(zName)</p>
    style_footer();
    return;
  }else if( rc==2 ){
    cgi_set_parameter("src","info");







|







1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
    }
    if( db_exists("SELECT 1 FROM tag WHERE tagname GLOB 'event-%q*'", zName) ){
      event_page();
      return;
    }
  }
  blob_set(&uuid, zName);
  rc = name_to_uuid(&uuid, -1, "*");
  if( rc==1 ){
    style_header("No Such Object");
    @ <p>No such object: %h(zName)</p>
    style_footer();
    return;
  }else if( rc==2 ){
    cgi_set_parameter("src","info");
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
  int fNewPropagateColor;       /* True if color propagates after edit */
  char *zUuid;
  Blob comment;
  Stmt q;
  
  login_check_credentials();
  if( !g.okWrite ){ login_needed(); return; }
  rid = name_to_rid(P("r"));
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
                        "  FROM event WHERE objid=%d", rid);
  if( zComment==0 ) fossil_redirect_home();
  if( P("cancel") ){
    cgi_redirectf("ci?name=%s", zUuid);
  }







|







1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
  int fNewPropagateColor;       /* True if color propagates after edit */
  char *zUuid;
  Blob comment;
  Stmt q;
  
  login_check_credentials();
  if( !g.okWrite ){ login_needed(); return; }
  rid = name_to_typed_rid(P("r"), "ci");
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  zComment = db_text(0, "SELECT coalesce(ecomment,comment)"
                        "  FROM event WHERE objid=%d", rid);
  if( zComment==0 ) fossil_redirect_home();
  if( P("cancel") ){
    cgi_redirectf("ci?name=%s", zUuid);
  }
Changes to src/manifest.c.
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
** Given a checkin name, load and parse the manifest for that checkin.
** Throw a fatal error if anything goes wrong.
*/
Manifest *manifest_get_by_name(const char *zName, int *pRid){
  int rid;
  Manifest *p;

  rid = name_to_rid(zName);
  if( !is_a_version(rid) ){
    fossil_fatal("no such checkin: %s", zName);
  }
  if( pRid ) *pRid = rid;
  p = manifest_get(rid, CFTYPE_MANIFEST);
  if( p==0 ){
    fossil_fatal("cannot parse manifest for checkin: %s", zName);







|







918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
** Given a checkin name, load and parse the manifest for that checkin.
** Throw a fatal error if anything goes wrong.
*/
Manifest *manifest_get_by_name(const char *zName, int *pRid){
  int rid;
  Manifest *p;

  rid = name_to_typed_rid(zName, "ci");
  if( !is_a_version(rid) ){
    fossil_fatal("no such checkin: %s", zName);
  }
  if( pRid ) *pRid = rid;
  p = manifest_get(rid, CFTYPE_MANIFEST);
  if( p==0 ){
    fossil_fatal("cannot parse manifest for checkin: %s", zName);
Changes to src/merge.c.
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  }
  db_must_be_within_tree();
  if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("nothing is checked out");
  }
  mid = name_to_rid(g.argv[2]);
  if( mid==0 || !is_a_version(mid) ){
    fossil_fatal("not a version: %s", g.argv[2]);
  }
  if( zPivot ){
    pid = name_to_rid(zPivot);
    if( pid==0 || !is_a_version(pid) ){
      fossil_fatal("not a version: %s", zPivot);
    }
    if( pickFlag ){
      fossil_fatal("incompatible options: --cherrypick & --baseline");
    }
    /* pickFlag = 1;  // Using --baseline is really like doing a cherrypick */







|




|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  }
  db_must_be_within_tree();
  if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("nothing is checked out");
  }
  mid = name_to_typed_rid(g.argv[2], "ci");
  if( mid==0 || !is_a_version(mid) ){
    fossil_fatal("not a version: %s", g.argv[2]);
  }
  if( zPivot ){
    pid = name_to_typed_rid(zPivot, "ci");
    if( pid==0 || !is_a_version(pid) ){
      fossil_fatal("not a version: %s", zPivot);
    }
    if( pickFlag ){
      fossil_fatal("incompatible options: --cherrypick & --baseline");
    }
    /* pickFlag = 1;  // Using --baseline is really like doing a cherrypick */
Changes to src/name.c.
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
** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
** If the input is of the form "date:*" or "localtime:*" or "utc:*" then
** always resolve the name as a date.
**
** Return 0 on success.  Return 1 if the name cannot be resolved.
** Return 2 name is ambiguous.
*/
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);
    }else{
      zUuid = tag_to_uuid(zName);
      if( zUuid==0 ){
        zUuid = date_to_uuid(zName);
      }
    }
    if( zUuid ){
      blob_reset(pName);
      blob_append(pName, zUuid, -1);
      free(zUuid);
      return 0;







|








|

|

|







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
** string YYYY-MM-DD HH:MM:SS and pick the nearest check-in to that date.
** If the input is of the form "date:*" or "localtime:*" or "utc:*" then
** always resolve the name as a date.
**
** Return 0 on success.  Return 1 if the name cannot be resolved.
** Return 2 name is ambiguous.
*/
int name_to_uuid(Blob *pName, int iErrPriority, const char *zType){
  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, zType);
    }else{
      zUuid = tag_to_uuid(zName, zType);
      if( zUuid==0 ){
        zUuid = date_to_uuid(zName, zType);
      }
    }
    if( zUuid ){
      blob_reset(pName);
      blob_append(pName, zUuid, -1);
      free(zUuid);
      return 0;
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    }
  }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);







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
    }
  }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);
139
140
141
142
143
144
145
146
147
148


149
150
151
152
153
154
155

156
157
158
159
160
161
162
163
164
** not older than 'date'.
**
** An input of "tip" returns the most recent check-in.
**
** Memory to hold the returned string comes from malloc() and needs to
** be freed by the caller.
*/
char *tag_to_uuid(const char *zTag){
  int vid;
  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
    );
  if( zUuid==0 ){
    int nTag = strlen(zTag);
    int i;
    for(i=0; i<nTag-10; i++){
      if( zTag[i]==':' && is_date(&zTag[i+1]) ){
        char *zDate = mprintf("%s", &zTag[i+1]);







|

|
>
>
|






>

|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
** not older than 'date'.
**
** An input of "tip" returns the most recent check-in.
**
** Memory to hold the returned string comes from malloc() and needs to
** be freed by the caller.
*/
char *tag_to_uuid(const char *zTag, const char *zType){
  int vid;
  char *zUuid;

  if( zType==0 || zType[0]==0 ) zType = "*";
  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 "
       "   AND event.type GLOB '%q'"
       " ORDER BY event.mtime DESC ",
       zTag, zType
    );
  if( zUuid==0 ){
    int nTag = strlen(zTag);
    int i;
    for(i=0; i<nTag-10; i++){
      if( zTag[i]==':' && is_date(&zTag[i+1]) ){
        char *zDate = mprintf("%s", &zTag[i+1]);
174
175
176
177
178
179
180

181
182
183
184
185
186
187
188
189
          "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 "
          "   AND event.mtime<=julianday(%Q %s)"

          " ORDER BY event.mtime DESC ",
          zTagBase, zDate, (useUtc ? "" : ",'utc'")
        );
        break;
      }
    }
    if( zUuid==0 && fossil_strcmp(zTag, "tip")==0 ){
      zUuid = db_text(0,
        "SELECT blob.uuid"







>

|







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
          "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 "
          "   AND event.mtime<=julianday(%Q %s)"
          "   AND event.type GLOB '%q'"
          " ORDER BY event.mtime DESC ",
          zTagBase, zDate, (useUtc ? "" : ",'utc'"), zType
        );
        break;
      }
    }
    if( zUuid==0 && fossil_strcmp(zTag, "tip")==0 ){
      zUuid = db_text(0,
        "SELECT blob.uuid"
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
**    date:DATE
**    local:DATE
**    utc:DATE
**
** The DATE is interpreted as localtime unless the "utc:" prefix is used
** or a "utc" string appears at the end of the DATE string.
*/
char *date_to_uuid(const char *zDate){
  int useUtc = 0;
  int n;
  char *zCopy = 0;
  char *zUuid;

  if( memcmp(zDate, "date:", 5)==0 ){
    zDate += 5;







|







224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
**    date:DATE
**    local:DATE
**    utc:DATE
**
** The DATE is interpreted as localtime unless the "utc:" prefix is used
** or a "utc" string appears at the end of the DATE string.
*/
char *date_to_uuid(const char *zDate, const char *zType){
  int useUtc = 0;
  int n;
  char *zCopy = 0;
  char *zUuid;

  if( memcmp(zDate, "date:", 5)==0 ){
    zDate += 5;
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315



316
317
318
319
320
321
322
  if( n>4 && sqlite3_strnicmp(&zDate[n-3], "utc", 3)==0 ){
    zCopy = mprintf("%s", zDate);
    zCopy[n-3] = 0;
    zDate = zCopy;
    n -= 3;
    useUtc = 1;
  }

  zUuid = db_text(0,
    "SELECT (SELECT uuid FROM blob WHERE rid=event.objid)"
    "  FROM event"
    " WHERE mtime<=julianday(%Q %s) AND type='ci'"
    " ORDER BY mtime DESC LIMIT 1",
    zDate, useUtc ? "" : ",'utc'"
  );
  free(zCopy);
  return zUuid;
}

/*
** COMMAND:  test-name-to-id
**
** Convert a name to a full artifact ID.
*/
void test_name_to_id(void){
  int i;
  Blob name;
  db_must_be_within_tree();
  for(i=2; i<g.argc; i++){
    blob_init(&name, g.argv[i], -1);
    fossil_print("%s -> ", g.argv[i]);
    if( name_to_uuid(&name, 1) ){
      fossil_print("ERROR: %s\n", g.zErrMsg);
      fossil_error_reset();
    }else{
      fossil_print("%s\n", blob_buffer(&name));
    }
    blob_reset(&name);
  }
}

/*
** Convert a name to a rid.  If the name is a small integer value then
** just use atoi() to do the conversion.  If the name contains alphabetic
** characters or is not an existing rid, then use name_to_uuid then
** convert the uuid to a rid.
**
** This routine is used by command-line routines to resolve command-line inputs
** into a rid.
*/
int name_to_rid(const char *zName){
  int i;
  int rid;
  Blob name;

  if( zName==0 || zName[0]==0 ) return 0;
  blob_init(&name, zName, -1);
  if( name_to_uuid(&name, -1) ){
    blob_reset(&name);
    for(i=0; zName[i] && fossil_isdigit(zName[i]); i++){}
    if( zName[i]==0 ){
      rid = atoi(zName);
      if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){
        return rid;
      }
    }
    fossil_error(1, "no such artifact: %s", zName);
    return 0;
  }else{
    rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name);
    blob_reset(&name);
  }
  return rid;
}




/*
** WEBPAGE: ambiguous
** URL: /ambiguous?name=UUID&src=WEBPAGE
** 
** The UUID given by the name paramager is ambiguous.  Display a page
** that shows all possible choices and let the user select between them.







>



|

|

















|


















|






|
















>
>
>







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
  if( n>4 && sqlite3_strnicmp(&zDate[n-3], "utc", 3)==0 ){
    zCopy = mprintf("%s", zDate);
    zCopy[n-3] = 0;
    zDate = zCopy;
    n -= 3;
    useUtc = 1;
  }
  if( zType==0 || zType[0]==0 ) zType = "*";
  zUuid = db_text(0,
    "SELECT (SELECT uuid FROM blob WHERE rid=event.objid)"
    "  FROM event"
    " WHERE mtime<=julianday(%Q %s) AND type GLOB '%q'"
    " ORDER BY mtime DESC LIMIT 1",
    zDate, useUtc ? "" : ",'utc'", zType
  );
  free(zCopy);
  return zUuid;
}

/*
** COMMAND:  test-name-to-id
**
** Convert a name to a full artifact ID.
*/
void test_name_to_id(void){
  int i;
  Blob name;
  db_must_be_within_tree();
  for(i=2; i<g.argc; i++){
    blob_init(&name, g.argv[i], -1);
    fossil_print("%s -> ", g.argv[i]);
    if( name_to_uuid(&name, 1, "*") ){
      fossil_print("ERROR: %s\n", g.zErrMsg);
      fossil_error_reset();
    }else{
      fossil_print("%s\n", blob_buffer(&name));
    }
    blob_reset(&name);
  }
}

/*
** Convert a name to a rid.  If the name is a small integer value then
** just use atoi() to do the conversion.  If the name contains alphabetic
** characters or is not an existing rid, then use name_to_uuid then
** convert the uuid to a rid.
**
** This routine is used by command-line routines to resolve command-line inputs
** into a rid.
*/
int name_to_typed_rid(const char *zName, const char *zType){
  int i;
  int rid;
  Blob name;

  if( zName==0 || zName[0]==0 ) return 0;
  blob_init(&name, zName, -1);
  if( name_to_uuid(&name, -1, zType) ){
    blob_reset(&name);
    for(i=0; zName[i] && fossil_isdigit(zName[i]); i++){}
    if( zName[i]==0 ){
      rid = atoi(zName);
      if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){
        return rid;
      }
    }
    fossil_error(1, "no such artifact: %s", zName);
    return 0;
  }else{
    rid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &name);
    blob_reset(&name);
  }
  return rid;
}
int name_to_rid(const char *zName){
  return name_to_typed_rid(zName, "*");
}

/*
** WEBPAGE: ambiguous
** URL: /ambiguous?name=UUID&src=WEBPAGE
** 
** The UUID given by the name paramager is ambiguous.  Display a page
** that shows all possible choices and let the user select between them.
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  int i, rc;
  int rid;
  const char *zName = P(zParamName);
  Blob name;

  if( zName==0 || zName[0]==0 ) return 0;
  blob_init(&name, zName, -1);
  rc = name_to_uuid(&name, -1);
  if( rc==1 ){
    blob_reset(&name);
    for(i=0; zName[i] && fossil_isdigit(zName[i]); i++){}
    if( zName[i]==0 ){
      rid = atoi(zName);
      if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){
        return rid;







|







367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
  int i, rc;
  int rid;
  const char *zName = P(zParamName);
  Blob name;

  if( zName==0 || zName[0]==0 ) return 0;
  blob_init(&name, zName, -1);
  rc = name_to_uuid(&name, -1, "*");
  if( rc==1 ){
    blob_reset(&name);
    for(i=0; zName[i] && fossil_isdigit(zName[i]); i++){}
    if( zName[i]==0 ){
      rid = atoi(zName);
      if( db_exists("SELECT 1 FROM blob WHERE rid=%d", rid) ){
        return rid;
Changes to src/tag.c.
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  Blob cksum;
  static const char zTagtype[] = { '-', '+', '*' };

  assert( tagtype>=0 && tagtype<=2 );
  user_select();
  blob_zero(&uuid);
  blob_append(&uuid, zObjName, -1);
  if( name_to_uuid(&uuid, 9) ){
    fossil_fatal("%s", g.zErrMsg);
    return;
  }
  rid = name_to_rid(blob_str(&uuid));
  g.markPrivate = content_is_private(rid);
  blob_zero(&ctrl);








|







294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
  Blob cksum;
  static const char zTagtype[] = { '-', '+', '*' };

  assert( tagtype>=0 && tagtype<=2 );
  user_select();
  blob_zero(&uuid);
  blob_append(&uuid, zObjName, -1);
  if( name_to_uuid(&uuid, 9, "*") ){
    fossil_fatal("%s", g.zErrMsg);
    return;
  }
  rid = name_to_rid(blob_str(&uuid));
  g.markPrivate = content_is_private(rid);
  blob_zero(&ctrl);

Changes to src/tar.c.
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  Blob tarball;
  const char *zName;
  zName = find_option("name", 0, 1);
  db_find_and_open_repository(0, 0);
  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  rid = name_to_rid(g.argv[2]);
  if( zName==0 ){
    zName = db_text("default-name",
       "SELECT replace(%Q,' ','_') "
          " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) "
          " || substr(blob.uuid, 1, 10)"
       "  FROM event, blob"
       " WHERE event.objid=%d"







|







271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  Blob tarball;
  const char *zName;
  zName = find_option("name", 0, 1);
  db_find_and_open_repository(0, 0);
  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  rid = name_to_typed_rid(g.argv[2], "ci");
  if( zName==0 ){
    zName = db_text("default-name",
       "SELECT replace(%Q,' ','_') "
          " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) "
          " || substr(blob.uuid, 1, 10)"
       "  FROM event, blob"
       " WHERE event.objid=%d"
Changes to src/timeline.c.
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
** If n= is missing, the default count is 20.
*/
void page_timeline(void){
  Stmt q;                            /* Query used to generate the timeline */
  Blob sql;                          /* text of SQL used to generate timeline */
  Blob desc;                         /* Description of the timeline */
  int nEntry = atoi(PD("n","20"));   /* Max number of entries on timeline */
  int p_rid = name_to_rid(P("p"));   /* artifact p and its parents */
  int d_rid = name_to_rid(P("d"));   /* artifact d and its descendants */
  int f_rid = name_to_rid(P("f"));   /* artifact f and immediate family */
  const char *zUser = P("u");        /* All entries by this user if not NULL */
  const char *zType = PD("y","all"); /* Type of events.  All if NULL */
  const char *zAfter = P("a");       /* Events after this time */
  const char *zBefore = P("b");      /* Events before this time */
  const char *zCirca = P("c");       /* Events near this time */
  const char *zTagName = P("t");     /* Show events with this tag */
  const char *zBrName = P("r");      /* Show events related to this tag */
  const char *zSearch = P("s");      /* Search string */
  int useDividers = P("nd")==0;      /* Show dividers if "nd" is missing */
  int tagid;                         /* Tag ID */
  int tmFlags;                       /* Timeline flags */
  const char *zThisTag = 0;          /* Suppress links to this tag */
  const char *zThisUser = 0;         /* Suppress links to this user */
  HQuery url;                        /* URL for various branch links */
  int from_rid = name_to_rid(P("from"));  /* from= for path timelines */
  int to_rid = name_to_rid(P("to"));      /* to= for path timelines */
  int noMerge = P("nomerge")!=0;          /* Do not follow merge links */
  int me_rid = name_to_rid(P("me"));    /* me= for common ancestory path */
  int you_rid = name_to_rid(P("you"));/* you= for common ancst path */

  /* To view the timeline, must have permission to read project data.
  */
  login_check_credentials();
  if( !g.okRead && !g.okRdTkt && !g.okRdWiki ){ login_needed(); return; }
  if( zTagName && g.okRead ){
    tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);







|
|
|














|
|

|
|







780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
** If n= is missing, the default count is 20.
*/
void page_timeline(void){
  Stmt q;                            /* Query used to generate the timeline */
  Blob sql;                          /* text of SQL used to generate timeline */
  Blob desc;                         /* Description of the timeline */
  int nEntry = atoi(PD("n","20"));   /* Max number of entries on timeline */
  int p_rid = name_to_typed_rid(P("p"),"ci");  /* artifact p and its parents */
  int d_rid = name_to_typed_rid(P("d"),"ci");  /* artifact d and descendants */
  int f_rid = name_to_typed_rid(P("f"),"ci");  /* artifact f and close family */
  const char *zUser = P("u");        /* All entries by this user if not NULL */
  const char *zType = PD("y","all"); /* Type of events.  All if NULL */
  const char *zAfter = P("a");       /* Events after this time */
  const char *zBefore = P("b");      /* Events before this time */
  const char *zCirca = P("c");       /* Events near this time */
  const char *zTagName = P("t");     /* Show events with this tag */
  const char *zBrName = P("r");      /* Show events related to this tag */
  const char *zSearch = P("s");      /* Search string */
  int useDividers = P("nd")==0;      /* Show dividers if "nd" is missing */
  int tagid;                         /* Tag ID */
  int tmFlags;                       /* Timeline flags */
  const char *zThisTag = 0;          /* Suppress links to this tag */
  const char *zThisUser = 0;         /* Suppress links to this user */
  HQuery url;                        /* URL for various branch links */
  int from_rid = name_to_typed_rid(P("from"),"ci"); /* from= for paths */
  int to_rid = name_to_typed_rid(P("to"),"ci");    /* to= for path timelines */
  int noMerge = P("nomerge")!=0;          /* Do not follow merge links */
  int me_rid = name_to_typed_rid(P("me"),"ci");  /* me= for common ancestory */
  int you_rid = name_to_typed_rid(P("you"),"ci");/* you= for common ancst */

  /* To view the timeline, must have permission to read project data.
  */
  login_check_credentials();
  if( !g.okRead && !g.okRdTkt && !g.okRdWiki ){ login_needed(); return; }
  if( zTagName && g.okRead ){
    tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
    zDate = mprintf("(SELECT datetime('now'))");
  }else if( strncmp(zOrigin, "current", k)==0 ){
    if( !g.localOpen ){
      fossil_fatal("must be within a local checkout to use 'current'");
    }
    objid = db_lget_int("checkout",0);
    zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid);
  }else if( name_to_uuid(&uuid, 0)==0 ){
    objid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
    zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid);
  }else{
    const char *zShift = "";
    if( mode==3 || mode==4 ){
      fossil_fatal("cannot compute descendants or ancestors of a date");
    }







|







1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
    zDate = mprintf("(SELECT datetime('now'))");
  }else if( strncmp(zOrigin, "current", k)==0 ){
    if( !g.localOpen ){
      fossil_fatal("must be within a local checkout to use 'current'");
    }
    objid = db_lget_int("checkout",0);
    zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid);
  }else if( name_to_uuid(&uuid, 0, "*")==0 ){
    objid = db_int(0, "SELECT rid FROM blob WHERE uuid=%B", &uuid);
    zDate = mprintf("(SELECT mtime FROM plink WHERE cid=%d)", objid);
  }else{
    const char *zShift = "";
    if( mode==3 || mode==4 ){
      fossil_fatal("cannot compute descendants or ancestors of a date");
    }
Changes to src/update.c.
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
      ** target as if VERSION were omitted. */
    }else if( fossil_strcmp(g.argv[2], "latest")==0 ){
      /* If VERSION is "latest", then use the same algorithm to find the
      ** target as if VERSION were omitted and the --latest flag is present.
      */
      latestFlag = 1;
    }else{
      tid = name_to_rid(g.argv[2]);
      if( tid==0 ){
        fossil_fatal("no such version: %s", g.argv[2]);
      }else if( !is_a_version(tid) ){
        fossil_fatal("no such version: %s", g.argv[2]);
      }
    }
  }







|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
      ** target as if VERSION were omitted. */
    }else if( fossil_strcmp(g.argv[2], "latest")==0 ){
      /* If VERSION is "latest", then use the same algorithm to find the
      ** target as if VERSION were omitted and the --latest flag is present.
      */
      latestFlag = 1;
    }else{
      tid = name_to_typed_rid(g.argv[2],"ci");
      if( tid==0 ){
        fossil_fatal("no such version: %s", g.argv[2]);
      }else if( !is_a_version(tid) ){
        fossil_fatal("no such version: %s", g.argv[2]);
      }
    }
  }
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
  int errCode              /* Error code if file not found.  Panic if 0. */
){
  Manifest *pManifest;
  ManifestFile *pFile;
  int rid=0;
  
  if( revision ){
    rid = name_to_rid(revision);
  }else{
    rid = db_lget_int("checkout", 0);
  }
  if( !is_a_version(rid) ){
    if( errCode>0 ) return errCode;
    fossil_fatal("no such checkin: %s", revision);
  }







|







471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
  int errCode              /* Error code if file not found.  Panic if 0. */
){
  Manifest *pManifest;
  ManifestFile *pFile;
  int rid=0;
  
  if( revision ){
    rid = name_to_typed_rid(revision,"ci");
  }else{
    rid = db_lget_int("checkout", 0);
  }
  if( !is_a_version(rid) ){
    if( errCode>0 ) return errCode;
    fossil_fatal("no such checkin: %s", revision);
  }
Changes to src/zip.c.
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  Blob zip;
  const char *zName;
  zName = find_option("name", 0, 1);
  db_find_and_open_repository(0, 0);
  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  rid = name_to_rid(g.argv[2]);
  if( zName==0 ){
    zName = db_text("default-name",
       "SELECT replace(%Q,' ','_') "
          " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) "
          " || substr(blob.uuid, 1, 10)"
       "  FROM event, blob"
       " WHERE event.objid=%d"







|







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
  Blob zip;
  const char *zName;
  zName = find_option("name", 0, 1);
  db_find_and_open_repository(0, 0);
  if( g.argc!=4 ){
    usage("VERSION OUTPUTFILE");
  }
  rid = name_to_typed_rid(g.argv[2],"ci");
  if( zName==0 ){
    zName = db_text("default-name",
       "SELECT replace(%Q,' ','_') "
          " || strftime('_%%Y-%%m-%%d_%%H%%M%%S_', event.mtime) "
          " || substr(blob.uuid, 1, 10)"
       "  FROM event, blob"
       " WHERE event.objid=%d"
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  nRid = strlen(zRid);
  for(nName=strlen(zName)-1; nName>5; nName--){
    if( zName[nName]=='.' ){
      zName[nName] = 0;
      break;
    }
  }
  rid = name_to_rid(nRid?zRid:zName);
  if( rid==0 ){
    @ Not found
    return;
  }
  if( nRid==0 && nName>10 ) zName[10] = 0;
  zip_of_baseline(rid, &zip, zName);
  free( zName );
  free( zRid );
  cgi_set_content(&zip);
  cgi_set_content_type("application/zip");
}







|











431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
  nRid = strlen(zRid);
  for(nName=strlen(zName)-1; nName>5; nName--){
    if( zName[nName]=='.' ){
      zName[nName] = 0;
      break;
    }
  }
  rid = name_to_typed_rid(nRid?zRid:zName,"ci");
  if( rid==0 ){
    @ Not found
    return;
  }
  if( nRid==0 && nName>10 ) zName[10] = 0;
  zip_of_baseline(rid, &zip, zName);
  free( zName );
  free( zRid );
  cgi_set_content(&zip);
  cgi_set_content_type("application/zip");
}