Fossil

Check-in [e17fc713]
Login

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

Overview
Comment:Change the definition of a "Leaf" to be any node that has no children of any kind (merge or non-merge) in the same branch. A "rebuild" or a "fossil leaves --recompute" is required to recompute the LEAF table after upgrading to this version.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:e17fc71319e0534b3c5bf2df9754bc6933c909dd
User & Date: drh 2011-04-25 22:23:56
Context
2011-04-27
02:10
Merge in the config-sync changes. This is a major schema change and definitely requires a "fossil rebuild". Note that the schema upgrade is irreversible and so you should be certain you want to continue with the new schema before you upgrade. check-in: 1654456e user: drh tags: trunk
2011-04-26
00:45
Begin implementing the protocol changes for configuration sync. check-in: f99e3fa9 user: drh tags: config-sync
2011-04-25
22:23
Change the definition of a "Leaf" to be any node that has no children of any kind (merge or non-merge) in the same branch. A "rebuild" or a "fossil leaves --recompute" is required to recompute the LEAF table after upgrading to this version. check-in: e17fc713 user: drh tags: trunk
20:26
Add hyperlink to the annotation of a file in the object description header. check-in: 030a0486 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/checkin.c.

464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
      g.aCommitFile[ii-2] = iId;
      blob_reset(&b);
    }
    g.aCommitFile[ii-2] = 0;
  }
}

/*
** Return true if the check-in with RID=rid is a leaf.
** A leaf has no primary children in the same branch. 
*/
int is_a_leaf(int rid){
  int rc;
  static const char zSql[] = 
    @ SELECT 1 FROM plink
    @  WHERE pid=%d
    @    AND coalesce((SELECT value FROM tagxref
    @                   WHERE tagid=%d AND rid=plink.pid), 'trunk')
    @       =coalesce((SELECT value FROM tagxref
    @                   WHERE tagid=%d AND rid=plink.cid), 'trunk')
    @    AND isprim
  ;
  rc = db_int(0, zSql, rid, TAG_BRANCH, TAG_BRANCH);
  return rc==0;
}

/*
** Make sure the current check-in with timestamp zDate is younger than its
** ancestor identified rid and zUuid.  Throw a fatal error if not.
*/
static void checkin_verify_younger(
  int rid,              /* The record ID of the ancestor */
  const char *zUuid,    /* The artifact ID of the ancestor */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







464
465
466
467
468
469
470



















471
472
473
474
475
476
477
      g.aCommitFile[ii-2] = iId;
      blob_reset(&b);
    }
    g.aCommitFile[ii-2] = 0;
  }
}




















/*
** Make sure the current check-in with timestamp zDate is younger than its
** ancestor identified rid and zUuid.  Throw a fatal error if not.
*/
static void checkin_verify_younger(
  int rid,              /* The record ID of the ancestor */
  const char *zUuid,    /* The artifact ID of the ancestor */

Changes to src/graph.c.

420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  */
  inUse = (1<<(p->mxRail+1))-1;
  for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
    int parentRid;

    if( pRow->iRail>=0 ){
      if( pRow->pChild==0 && !pRow->timeWarp ){
        if( pRow->isLeaf || omitDescenders ){
          inUse &= ~(1<<pRow->iRail);
        }else{
          pRow->aiRiser[pRow->iRail] = 0;
          mask = 1<<pRow->iRail;
          for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){
            pLoop->railInUse |= mask;
          }







|







420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  */
  inUse = (1<<(p->mxRail+1))-1;
  for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
    int parentRid;

    if( pRow->iRail>=0 ){
      if( pRow->pChild==0 && !pRow->timeWarp ){
        if( omitDescenders || count_nonbranch_children(pRow->rid)==0 ){
          inUse &= ~(1<<pRow->iRail);
        }else{
          pRow->aiRiser[pRow->iRail] = 0;
          mask = 1<<pRow->iRail;
          for(pLoop=pRow; pLoop; pLoop=pLoop->pPrev){
            pLoop->railInUse |= mask;
          }

Changes to src/info.c.

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
  }
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  zParent = db_text(0,
    "SELECT uuid FROM plink, blob"
    " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
    rid
  );
  isLeaf = !db_exists("SELECT 1 FROM plink WHERE pid=%d", rid);
  db_prepare(&q, 
     "SELECT uuid, datetime(mtime, 'localtime'), user, comment,"
     "       datetime(omtime, 'localtime')"
     "  FROM blob, event"
     " WHERE blob.rid=%d"
     "   AND event.objid=%d",
     rid, rid







|







366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
  }
  zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
  zParent = db_text(0,
    "SELECT uuid FROM plink, blob"
    " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
    rid
  );
  isLeaf = is_a_leaf(rid);
  db_prepare(&q, 
     "SELECT uuid, datetime(mtime, 'localtime'), user, comment,"
     "       datetime(omtime, 'localtime')"
     "  FROM blob, event"
     " WHERE blob.rid=%d"
     "   AND event.objid=%d",
     rid, rid

Changes to src/leaf.c.

21
22
23
24
25
26
27

















































28
29
30
31
32
33
34
..
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
** The LEAF table contains the rids for all leaves in the checkin DAG.
** A leaf is a checkin that has no children in the same branch.
*/
#include "config.h"
#include "leaf.h"
#include <assert.h>



















































/*
** Recompute the entire LEAF table.  
**
** This can be expensive (5 seconds or so) for a really large repository.
** So it is only done for things like a rebuild.
*/
................................................................................
    "INSERT OR IGNORE INTO leaf"
    "  SELECT cid FROM plink"
    "  EXCEPT"
    "  SELECT pid FROM plink"
    "   WHERE coalesce((SELECT value FROM tagxref"
                       " WHERE tagid=%d AND rid=plink.pid),'trunk')"
         " == coalesce((SELECT value FROM tagxref"
                       " WHERE tagid=%d AND rid=plink.cid),'trunk')"
      "   AND isprim",
    TAG_BRANCH, TAG_BRANCH
  );
}

/*
** A bag of checkins whose leaf status needs to be checked.
*/
................................................................................
  static Stmt checkIfLeaf;
  static Stmt addLeaf;
  static Stmt removeLeaf;
  int rc;

  db_static_prepare(&checkIfLeaf,
    "SELECT 1 FROM plink"
    " WHERE pid=:rid AND isprim"
    "   AND coalesce((SELECT value FROM tagxref"
                    " WHERE tagid=%d AND rid=:rid),'trunk')"
       " == coalesce((SELECT value FROM tagxref"
                    " WHERE tagid=%d AND rid=plink.cid),'trunk');",
    TAG_BRANCH, TAG_BRANCH
  );
  db_bind_int(&checkIfLeaf, ":rid", rid);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
<







 







|







21
22
23
24
25
26
27
28
29
30
31
32
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
..
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
** The LEAF table contains the rids for all leaves in the checkin DAG.
** A leaf is a checkin that has no children in the same branch.
*/
#include "config.h"
#include "leaf.h"
#include <assert.h>


/*
** Return true if the check-in with RID=rid is a leaf.
**
** A leaf has no children in the same branch. 
*/
int is_a_leaf(int rid){
  int rc;
  static const char zSql[] = 
    @ SELECT 1 FROM plink
    @  WHERE pid=%d
    @    AND coalesce((SELECT value FROM tagxref
    @                   WHERE tagid=%d AND rid=plink.pid), 'trunk')
    @       =coalesce((SELECT value FROM tagxref
    @                   WHERE tagid=%d AND rid=plink.cid), 'trunk')
  ;
  rc = db_int(0, zSql, rid, TAG_BRANCH, TAG_BRANCH);
  return rc==0;
}

/*
** Count the number of primary non-branch children for the given check-in.
**
** A primary child is one where the parent is the primary parent, not
** a merge parent.  A "leaf" is a node that has zero children of any
** kind.  This routine counts only primary children.
**
** A non-branch child is one which is on the same branch as the parent.
*/
int count_nonbranch_children(int pid){
  int nNonBranch = 0;
  static Stmt q;
  static const char zSql[] = 
    @ SELECT count(*) FROM plink
    @  WHERE pid=:pid AND isprim
    @    AND coalesce((SELECT value FROM tagxref
    @                   WHERE tagid=%d AND rid=plink.pid), 'trunk')
    @       =coalesce((SELECT value FROM tagxref
    @                   WHERE tagid=%d AND rid=plink.cid), 'trunk')
  ;
  db_static_prepare(&q, zSql, TAG_BRANCH, TAG_BRANCH);
  db_bind_int(&q, ":pid", pid);
  if( db_step(&q)==SQLITE_ROW ){
    nNonBranch = db_column_int(&q, 0);
  }
  db_reset(&q);
  return nNonBranch;
}


/*
** Recompute the entire LEAF table.  
**
** This can be expensive (5 seconds or so) for a really large repository.
** So it is only done for things like a rebuild.
*/
................................................................................
    "INSERT OR IGNORE INTO leaf"
    "  SELECT cid FROM plink"
    "  EXCEPT"
    "  SELECT pid FROM plink"
    "   WHERE coalesce((SELECT value FROM tagxref"
                       " WHERE tagid=%d AND rid=plink.pid),'trunk')"
         " == coalesce((SELECT value FROM tagxref"
                       " WHERE tagid=%d AND rid=plink.cid),'trunk')",

    TAG_BRANCH, TAG_BRANCH
  );
}

/*
** A bag of checkins whose leaf status needs to be checked.
*/
................................................................................
  static Stmt checkIfLeaf;
  static Stmt addLeaf;
  static Stmt removeLeaf;
  int rc;

  db_static_prepare(&checkIfLeaf,
    "SELECT 1 FROM plink"
    " WHERE pid=:rid"
    "   AND coalesce((SELECT value FROM tagxref"
                    " WHERE tagid=%d AND rid=:rid),'trunk')"
       " == coalesce((SELECT value FROM tagxref"
                    " WHERE tagid=%d AND rid=plink.cid),'trunk');",
    TAG_BRANCH, TAG_BRANCH
  );
  db_bind_int(&checkIfLeaf, ":rid", rid);

Changes to src/name.c.

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
      }else if( fossil_strcmp(zTag, "prev")==0 
                || fossil_strcmp(zTag, "previous")==0 ){
        zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
                           "(SELECT pid FROM plink WHERE cid=%d AND isprim)",
                           vid);
      }else if( fossil_strcmp(zTag, "next")==0 ){
        zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
                           "(SELECT cid FROM plink WHERE pid=%d AND isprim"
                           "  ORDER BY mtime DESC)",
                           vid);
      }
    }
  }
  return zUuid;
}








|
|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
      }else if( fossil_strcmp(zTag, "prev")==0 
                || fossil_strcmp(zTag, "previous")==0 ){
        zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
                           "(SELECT pid FROM plink WHERE cid=%d AND isprim)",
                           vid);
      }else if( fossil_strcmp(zTag, "next")==0 ){
        zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid="
                           "(SELECT cid FROM plink WHERE pid=%d"
                           "  ORDER BY isprim DESC, mtime DESC)",
                           vid);
      }
    }
  }
  return zUuid;
}

Changes to src/timeline.c.

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
      @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
    }
  }else{
    @ %s(zU)
  }
}

/*
** Count the number of primary non-branch children for the given check-in.
**
** A primary child is one where the parent is the primary parent, not
** a merge parent.
**
** A non-branch child is one which is on the same branch as the parent.
*/
int count_nonbranch_children(int pid){
  int nNonBranch;
  static const char zSql[] = 
    @ SELECT count(*) FROM plink
    @  WHERE pid=%d AND isprim
    @    AND coalesce((SELECT value FROM tagxref
    @                   WHERE tagid=%d AND rid=plink.pid), 'trunk')
    @       =coalesce((SELECT value FROM tagxref
    @                   WHERE tagid=%d AND rid=plink.cid), 'trunk')
  ;
  nNonBranch = db_int(0, zSql, pid, TAG_BRANCH, TAG_BRANCH);
  return nNonBranch;
}

/*
** Allowed flags for the tmFlags argument to www_print_timeline
*/
#if INTERFACE
#define TIMELINE_ARTID    0x0001  /* Show artifact IDs on non-check-in lines */
#define TIMELINE_LEAFONLY 0x0002  /* Show "Leaf", but not "Merge", "Fork" etc */
#define TIMELINE_BRIEF    0x0004  /* Combine adjacent elements of same object */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







95
96
97
98
99
100
101






















102
103
104
105
106
107
108
      @ <a href="%s(g.zTop)/timeline?u=%T(zU)">%h(zU)</a>%s(zSuf)
    }
  }else{
    @ %s(zU)
  }
}























/*
** Allowed flags for the tmFlags argument to www_print_timeline
*/
#if INTERFACE
#define TIMELINE_ARTID    0x0001  /* Show artifact IDs on non-check-in lines */
#define TIMELINE_LEAFONLY 0x0002  /* Show "Leaf", but not "Merge", "Fork" etc */
#define TIMELINE_BRIEF    0x0004  /* Combine adjacent elements of same object */

Changes to test/graph-test-1.wiki.

58
59
60
61
62
63
64
65


66
67
68
69
70
     From e663bac6f7 to a298a0e2f9 by shortest path.</a>
  *  <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9&nomerge"
     target="testwindow">
     From e663bac6f7 to a298a0e2f9 without merge links.</a>
  *  <a href="../../../timeline?me=e663bac6f7&you=a298a0e2f9"
     target="testwindow">
     Common ancestor path of e663bac6f7 to a298a0e2f9.</a>




External:

  *  <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
     target="testwindow">Timewarp due to a mis-configured system clock.</a>







|
>
>





58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
     From e663bac6f7 to a298a0e2f9 by shortest path.</a>
  *  <a href="../../../timeline?from=e663bac6f7&to=a298a0e2f9&nomerge"
     target="testwindow">
     From e663bac6f7 to a298a0e2f9 without merge links.</a>
  *  <a href="../../../timeline?me=e663bac6f7&you=a298a0e2f9"
     target="testwindow">
     Common ancestor path of e663bac6f7 to a298a0e2f9.</a>
  *  <a href="../../../timeline?f=65dd90fb95a2af55">
     Merge on the same branch does not result in a leaf.
     </a>

External:

  *  <a href="http://www.sqlite.org/src/timeline?c=2010-09-29&nd"
     target="testwindow">Timewarp due to a mis-configured system clock.</a>