Fossil

Check-in [41dc5fc000]
Login

Check-in [41dc5fc000]

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

Overview
Comment:Fix the describe_commit() routine so that it is faster and simpler and so that it ignores tags that are applied to more than one check-in.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 41dc5fc000618313eaceae274ee4b1f5ac479f41b36961db7427d53b3176bbd7
User & Date: drh 2022-03-30 21:11:13.132
Context
2022-03-31
08:21
In "fossil describe", use hash_digits() as the default length when printing the commit hash. ... (check-in: 951cf9faf3 user: danield tags: trunk)
2022-03-30
21:11
Fix the describe_commit() routine so that it is faster and simpler and so that it ignores tags that are applied to more than one check-in. ... (check-in: 41dc5fc000 user: drh tags: trunk)
14:45
Add the new "fossil describe" command. ... (check-in: 36ca266479 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/info.c.
3703
3704
3705
3706
3707
3708
3709
3710


3711

3712
3713
3714
3715
3716
3717
3718
**
** Return values:
**       0: ok
**      -1: zName does not resolve to a commit
**      -2: zName resolves to more than a commit
**      -3: no ancestor commit with a fitting non-propagating tag found
*/
int describe_commit(const char *zName, const char *matchGlob,


                    CommitDescr *descr){

  int rid;             /* rid for zName */
  const char *zUuid;   /* Hash of rid */
  int nRet = 0;        /* Value to be returned */
  Stmt q;              /* Query for tagged ancestors */

  rid = symbolic_name_to_rid(zName, "ci"); /* only commits */








|
>
>
|
>







3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
**
** Return values:
**       0: ok
**      -1: zName does not resolve to a commit
**      -2: zName resolves to more than a commit
**      -3: no ancestor commit with a fitting non-propagating tag found
*/
int describe_commit(
  const char *zName,       /* Name of the commit to be described */
  const char *matchGlob,   /* Glob pattern for the tag */
  CommitDescr *descr       /* Write the description here */
){
  int rid;             /* rid for zName */
  const char *zUuid;   /* Hash of rid */
  int nRet = 0;        /* Value to be returned */
  Stmt q;              /* Query for tagged ancestors */

  rid = symbolic_name_to_rid(zName, "ci"); /* only commits */

3726
3727
3728
3729
3730
3731
3732
3733
3734



3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770


3771
3772
3773

3774


3775
3776
3777






3778
3779

3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
  }

  zUuid = rid_to_uuid(rid);
  descr->zCommitHash = mprintf("%s", zUuid);
  descr->isDirty = unsaved_changes(0);

  db_multi_exec(
    "DROP TABLE IF EXISTS singletonTaggedAncestors;"
    "CREATE TEMP TABLE singletonTaggedAncestors AS"



    "  WITH RECURSIVE "
    "  singletonTaggedCommits(rid,mtime,shorttag) AS ("
    "    SELECT DISTINCT b.rid,e.mtime,substr(t.tagname,5) AS shorttag"
    "          FROM blob b"
    "    INNER JOIN event e ON e.objid=b.rid"
    "    INNER JOIN tagxref tx ON tx.rid=b.rid"
    "    INNER JOIN tag t ON t.tagid=tx.tagid"
    "         WHERE e.type='ci'"
    "           AND tx.tagtype=1"
    "           AND t.tagname GLOB 'sym-%q'"
    "  ),"
    "  parent(pid,cid,isCP,isPrim) AS ("
    "    SELECT plink.pid, plink.cid, 0, isPrim FROM plink"
    "    UNION ALL"
    "    SELECT parentid, childid, 1, 0 FROM cherrypick WHERE NOT isExclude"
    "  ),"
    "  ancestor(rid, mtime, isCP, isPrim) AS ("
    "    SELECT objid, mtime, 0, 1 FROM event WHERE objid=%d"
    "    UNION"
    "    SELECT parent.pid, event.mtime, parent.isCP, parent.isPrim"
    "      FROM ancestor, parent, event"
    "     WHERE parent.cid=ancestor.rid"
    "       AND event.objid=parent.pid"
    "       AND NOT ancestor.isCP"
    "       AND (event.mtime >= "
    "              (SELECT max(mtime) FROM singletonTaggedCommits"
    "                 WHERE mtime<=(SELECT mtime FROM event WHERE objid=%d)))"
    "     ORDER BY mtime DESC"
    "     LIMIT 1000000"
    "  ) "
    "SELECT rid, mtime, isCP, isPrim, ROW_NUMBER() OVER (ORDER BY mtime DESC) rn"
    "  FROM ancestor",
    (matchGlob ? matchGlob : "*"), rid, rid
  );

  db_prepare(&q,


    "SELECT ta.rid, ta.mtime, ta.rn, b.uuid, substr(t.tagname, 5)"
    "        FROM singletonTaggedAncestors ta"
    "  INNER JOIN blob b ON b.rid=ta.rid"

    "  INNER JOIN tagxref tx ON tx.rid=ta.rid"


    "  INNER JOIN tag t ON tx.tagid=t.tagid"
    "       WHERE tx.tagtype=1 AND t.tagname GLOB 'sym-%q' "
    "         AND rn=(SELECT MAX(rn) FROM singletonTaggedAncestors)"






    "    ORDER BY tx.mtime DESC, t.tagname DESC LIMIT 1",
    (matchGlob ? matchGlob : "*")     

  );

  if( db_step(&q)==SQLITE_ROW ){
    const char *lastTag = db_column_text(&q, 4);
    descr->zRelTagname = mprintf("%s", lastTag);
    descr->nCommitsSince = db_column_int(&q, 2)-1;
    nRet = 0;
  }else{
    /* no ancestor commit with a fitting singleton tag found */
    descr->zRelTagname = mprintf("");
    descr->nCommitsSince = -1;
    nRet = -3;
  }







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



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



|

|







3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745


3746
3747
3748








3749










3750


3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773

3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
  }

  zUuid = rid_to_uuid(rid);
  descr->zCommitHash = mprintf("%s", zUuid);
  descr->isDirty = unsaved_changes(0);

  db_multi_exec(
    "DROP TABLE IF EXISTS temp.singletonTag;"
    "CREATE TEMP TABLE singletonTag("
    "  rid INT,"
    "  tagname TEXT,"
    "  PRIMARY KEY (rid,tagname)"
    ") WITHOUT ROWID;"
    "INSERT OR IGNORE INTO singletonTag(rid, tagname)"
    "  SELECT min(rid),"
    "         substr(tagname,5)"
    "    FROM tag, tagxref"


    "   WHERE tag.tagid=tagxref.tagid"
    "     AND tagxref.tagtype=1"
    "     AND tagname GLOB 'sym-%q'"








    "   GROUP BY tagname"










    "  HAVING count(*)==1;",


    (matchGlob ? matchGlob : "*")
  );

  db_prepare(&q,
    "WITH RECURSIVE"
    "  ancestor(rid,mtime,tagname,n) AS ("
    "    SELECT %d, event.mtime, singletonTag.tagname, 0 "
    "      FROM event"
    "      LEFT JOIN singletonTag ON singletonTag.rid=event.objid"
    "     WHERE event.objid=%d"
    "     UNION ALL"
    "     SELECT plink.pid, event.mtime, singletonTag.tagname, n+1"
    "       FROM ancestor, plink, event"
    "       LEFT JOIN singletonTag ON singletonTag.rid=plink.pid"
    "      WHERE plink.cid=ancestor.rid"
    "        AND event.objid=plink.pid"
    "        AND ancestor.tagname IS NULL"
    "      ORDER BY mtime DESC"
    "  )"
    "SELECT tagname, n"
    "  FROM ancestor"
    " WHERE tagname IS NOT NULL"
    " ORDER BY n LIMIT 1;",

    rid, rid
  );

  if( db_step(&q)==SQLITE_ROW ){
    const char *lastTag = db_column_text(&q, 0);
    descr->zRelTagname = mprintf("%s", lastTag);
    descr->nCommitsSince = db_column_int(&q, 1);
    nRet = 0;
  }else{
    /* no ancestor commit with a fitting singleton tag found */
    descr->zRelTagname = mprintf("");
    descr->nCommitsSince = -1;
    nRet = -3;
  }