Changes On Branch path-refactor
Not logged in

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

Changes In Branch path-refactor Excluding Merge-Ins

This is equivalent to a diff from c7f07fe67d to cfec72248e

2011-03-14
12:42
Merge the path-refactor changes into trunk. Refactoring is not complete, but it appears to be stable. check-in: e5121b4762 user: drh tags: trunk
2011-03-10
17:42
Show the name of the user that is doing the commit in the prompt section commit comment template. check-in: cdc4249268 user: drh tags: trunk
17:39
Add the ability to compute common ancestors to the path object. Still using the pivot object for merges, however. Closed-Leaf check-in: cfec72248e user: drh tags: path-refactor
02:39
Refactoring the DAG path search code into a separate object. check-in: 34c23c6fd4 user: drh tags: path-refactor
2011-03-09
23:16
Add a graph-generation test case for time-warp. check-in: c7f07fe67d user: drh tags: trunk
22:56
Show a path timeline without extraneous decoration. check-in: d37c6a4bc1 user: drh tags: trunk

Changes to src/bisect.c.

    19     19   ** This file also contains logic used to compute the closure of filename
    20     20   ** changes that have occurred across multiple check-ins.
    21     21   */
    22     22   #include "config.h"
    23     23   #include "bisect.h"
    24     24   #include <assert.h>
    25     25   
    26         -#if INTERFACE
    27         -/* Nodes for the shortest path algorithm.
    28         -*/
    29         -struct BisectNode {
    30         -  int rid;                 /* ID for this node */
    31         -  int fromIsParent;        /* True if pFrom is the parent of rid */
    32         -  BisectNode *pFrom;       /* Node we came from */
    33         -  union {
    34         -    BisectNode *pPeer;       /* List of nodes of the same generation */
    35         -    BisectNode *pTo;         /* Next on path from beginning to end */
    36         -  } u;
    37         -  BisectNode *pAll;        /* List of all nodes */
    38         -};
    39         -#endif
    40         -
    41     26   /*
    42     27   ** Local variables for this module
    43     28   */
    44     29   static struct {
    45         -  BisectNode *pCurrent;   /* Current generation of nodes */
    46         -  BisectNode *pAll;       /* All nodes */
    47         -  Bag seen;               /* Nodes seen before */
    48     30     int bad;                /* The bad version */
    49     31     int good;               /* The good version */
    50         -  int nStep;              /* Number of steps from good to bad */
    51         -  BisectNode *pStart;     /* Earliest node (bad) */
    52         -  BisectNode *pEnd;       /* Most recent (good) */
    53     32   } bisect;
    54     33   
    55         -/*
    56         -** Create a new node
    57         -*/
    58         -static BisectNode *bisect_new_node(int rid, BisectNode *pFrom, int isParent){
    59         -  BisectNode *p;
    60         -
    61         -  p = fossil_malloc( sizeof(*p) );
    62         -  p->rid = rid;
    63         -  p->fromIsParent = isParent;
    64         -  p->pFrom = pFrom;
    65         -  p->u.pPeer = bisect.pCurrent;
    66         -  bisect.pCurrent = p;
    67         -  p->pAll = bisect.pAll;
    68         -  bisect.pAll = p;
    69         -  bisect.pEnd = p;
    70         -  bag_insert(&bisect.seen, rid);
    71         -  return p;
    72         -}
    73         -
    74         -/*
    75         -** Reset memory used by the shortest path algorithm.
    76         -*/
    77         -void bisect_reset(void){
    78         -  BisectNode *p;
    79         -  while( bisect.pAll ){
    80         -    p = bisect.pAll;
    81         -    bisect.pAll = p->pAll;
    82         -    fossil_free(p);
    83         -  }
    84         -  bag_clear(&bisect.seen);
    85         -  bisect.pCurrent = 0;
    86         -  bisect.pAll = 0;
    87         -  bisect.pEnd = 0;
    88         -  bisect.nStep = 0;
    89         -}
    90         -
    91         -/*
    92         -** Compute the shortest path from iFrom to iTo
    93         -**
    94         -** If directOnly is true, then use only the "primary" links from parent to
    95         -** child.  In other words, ignore merges.
    96         -*/
    97         -BisectNode *bisect_shortest_path(int iFrom, int iTo, int directOnly){
    98         -  Stmt s;
    99         -  BisectNode *pPrev;
   100         -  BisectNode *p;
   101         -
   102         -  bisect_reset();
   103         -  bisect.pStart = bisect_new_node(iFrom, 0, 0);
   104         -  if( iTo==iFrom ) return bisect.pStart;
   105         -  if( directOnly ){
   106         -    db_prepare(&s, 
   107         -        "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim "
   108         -        "UNION ALL "
   109         -        "SELECT pid, 0 FROM plink WHERE cid=:pid AND isprim"
   110         -    );
   111         -  }else{
   112         -    db_prepare(&s, 
   113         -        "SELECT cid, 1 FROM plink WHERE pid=:pid "
   114         -        "UNION ALL "
   115         -        "SELECT pid, 0 FROM plink WHERE cid=:pid"
   116         -    );
   117         -  }
   118         -  while( bisect.pCurrent ){
   119         -    bisect.nStep++;
   120         -    pPrev = bisect.pCurrent;
   121         -    bisect.pCurrent = 0;
   122         -    while( pPrev ){
   123         -      db_bind_int(&s, ":pid", pPrev->rid);
   124         -      while( db_step(&s)==SQLITE_ROW ){
   125         -        int cid = db_column_int(&s, 0);
   126         -        int isParent = db_column_int(&s, 1);
   127         -        if( bag_find(&bisect.seen, cid) ) continue;
   128         -        p = bisect_new_node(cid, pPrev, isParent);
   129         -        if( cid==iTo ){
   130         -          db_finalize(&s);
   131         -          return p;
   132         -        }
   133         -      }
   134         -      db_reset(&s);
   135         -      pPrev = pPrev->u.pPeer;
   136         -    }
   137         -  }
   138         -  bisect_reset();
   139         -  return 0;
   140         -}
   141         -
   142         -/*
   143         -** Construct the path from bisect.pStart to bisect.pEnd in the u.pTo fields.
   144         -*/
   145         -BisectNode *bisect_reverse_path(void){
   146         -  BisectNode *p;
   147         -  for(p=bisect.pEnd; p && p->pFrom; p = p->pFrom){
   148         -    p->pFrom->u.pTo = p;
   149         -  }
   150         -  bisect.pEnd->u.pTo = 0;
   151         -  assert( p==bisect.pStart );
   152         -  return p;
   153         -}
   154         -
   155         -/*
   156         -** COMMAND:  test-shortest-path
   157         -**
   158         -** Usage: %fossil test-shortest-path ?--no-merge? VERSION1 VERSION2
   159         -**
   160         -** Report the shortest path between two checkins.  If the --no-merge flag
   161         -** is used, follow only direct parent-child paths and omit merge links.
   162         -*/
   163         -void shortest_path_test_cmd(void){
   164         -  int iFrom;
   165         -  int iTo;
   166         -  BisectNode *p;
   167         -  int n;
   168         -  int directOnly;
   169         -
   170         -  db_find_and_open_repository(0,0);
   171         -  directOnly = find_option("no-merge",0,0)!=0;
   172         -  if( g.argc!=4 ) usage("VERSION1 VERSION2");
   173         -  iFrom = name_to_rid(g.argv[2]);
   174         -  iTo = name_to_rid(g.argv[3]);
   175         -  p = bisect_shortest_path(iFrom, iTo, directOnly);
   176         -  if( p==0 ){
   177         -    fossil_fatal("no path from %s to %s", g.argv[1], g.argv[2]);
   178         -  }
   179         -  bisect_reverse_path();
   180         -  for(n=1, p=bisect.pStart; p; p=p->u.pTo, n++){
   181         -    char *z;
   182         -    z = db_text(0,
   183         -      "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
   184         -      "  FROM blob, event"
   185         -      " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
   186         -      p->rid, p->rid);
   187         -    printf("%4d: %s", n, z);
   188         -    fossil_free(z);
   189         -    if( p->u.pTo ){
   190         -      printf(" is a %s of\n", p->u.pTo->fromIsParent ? "parent" : "child");
   191         -    }else{
   192         -      printf("\n");
   193         -    }
   194         -  }
   195         -}
   196         -
   197         -/*
   198         -** WEBPAGE:  path
   199         -**
   200         -** example:  /path?from=trunk&to=experimental&nomerge
   201         -**
   202         -** Show a timeline of all changes along a path between two versions.
   203         -*/
   204         -void path_page(void){
   205         -  login_check_credentials();
   206         -  if( !g.okRead ){ login_needed(); return; }
   207         -}
   208         -
   209     34   /*
   210     35   ** Find the shortest path between bad and good.
   211     36   */
   212         -static BisectNode *bisect_path(void){
   213         -  BisectNode *p;
           37  +void bisect_path(void){
           38  +  PathNode *p;
   214     39     bisect.bad = db_lget_int("bisect-bad", 0);
   215     40     if( bisect.bad==0 ){
   216     41       bisect.bad = db_int(0, "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1");
   217     42       db_lset_int("bisect-bad", bisect.bad);
   218     43     }
   219     44     bisect.good = db_lget_int("bisect-good", 0);
   220     45     if( bisect.good==0 ){
   221     46       bisect.good = db_int(0,"SELECT pid FROM plink ORDER BY mtime LIMIT 1");
   222     47       db_lset_int("bisect-good", bisect.good);
   223     48     }
   224         -  p = bisect_shortest_path(bisect.good, bisect.bad, 0);
           49  +  p = path_shortest(bisect.good, bisect.bad, 0);
   225     50     if( p==0 ){
   226     51       char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
   227     52       char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
   228     53       fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
   229     54                    zGood, zBad);
   230     55     }
   231         -  return p;
   232     56   }
   233         -
   234         -
   235     57   
   236     58   /*
   237     59   ** COMMAND: bisect
   238     60   **
   239     61   ** Usage: %fossil bisect SUBCOMMAND ...
   240     62   **
   241     63   ** Run various subcommands useful for searching for bugs.
................................................................................
   284    106       if( g.argc==3 ){
   285    107         ridGood = db_lget_int("checkout",0);
   286    108       }else{
   287    109         ridGood = name_to_rid(g.argv[3]);
   288    110       }
   289    111       db_lset_int("bisect-good", ridGood);
   290    112     }else if( memcmp(zCmd, "next", n)==0 ){
   291         -    BisectNode *p;
   292         -    int n;
          113  +    PathNode *pMid;
   293    114       bisect_path();
   294         -    if( bisect.nStep<2 ){
          115  +    pMid = path_midpoint();
          116  +    if( pMid==0 ){
   295    117         fossil_fatal("bisect is done - there are no more intermediate versions");
   296    118       }
   297         -    for(p=bisect.pEnd, n=0; p && n<bisect.nStep/2; p=p->pFrom, n++){}
   298    119       g.argv[1] = "update";
   299         -    g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid);
          120  +    g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
   300    121       g.argc = 3;
   301    122       g.fNoSync = 1;
   302    123       update_cmd();
   303    124     }else if( memcmp(zCmd, "reset", n)==0 ){
   304    125       db_multi_exec(
   305    126         "REPLACE INTO vvar(name, value) "
   306    127         "  SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;"
   307    128         "REPLACE INTO vvar(name, value) "
   308    129         "  SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;"
   309    130       );
   310    131     }else if( memcmp(zCmd, "vlist", n)==0 ){
   311         -    BisectNode *p;
          132  +    PathNode *p;
   312    133       int vid = db_lget_int("checkout", 0);
   313    134       int n;
   314    135       Stmt s;
          136  +    int nStep;
   315    137       bisect_path();
   316    138       db_prepare(&s, "SELECT substr(blob.uuid,1,20) || ' ' || "
   317    139                      "       datetime(event.mtime) FROM blob, event"
   318    140                      " WHERE blob.rid=:rid AND event.objid=:rid"
   319    141                      "   AND event.type='ci'");
   320         -    for(p=bisect.pEnd, n=0; p; p=p->pFrom, n++){
          142  +    nStep = path_length();
          143  +    for(p=path_last(), n=0; p; p=p->pFrom, n++){
   321    144         const char *z;
   322    145         db_bind_int(&s, ":rid", p->rid);
   323    146         if( db_step(&s)==SQLITE_ROW ){
   324    147           z = db_column_text(&s, 0);
   325    148           printf("%s", z);
   326    149           if( p->rid==bisect.good ) printf(" GOOD");
   327    150           if( p->rid==bisect.bad ) printf(" BAD");
   328    151           if( p->rid==vid ) printf(" CURRENT");
   329         -        if( bisect.nStep>1 && n==bisect.nStep/2 ) printf(" NEXT");
          152  +        if( nStep>1 && n==nStep/2 ) printf(" NEXT");
   330    153           printf("\n");
   331    154         }
   332    155         db_reset(&s);
   333    156       }
   334    157       db_finalize(&s);
   335    158     }else{
   336    159       usage("bad|good|next|reset|vlist ...");
   337    160     }
   338    161   }
   339         -
   340         -/*
   341         -** A record of a file rename operation.
   342         -*/
   343         -typedef struct NameChange NameChange;
   344         -struct NameChange {
   345         -  int origName;        /* Original name of file */
   346         -  int curName;         /* Current name of the file */
   347         -  int newName;         /* Name of file in next version */
   348         -  NameChange *pNext;   /* List of all name changes */
   349         -};
   350         -
   351         -/*
   352         -** Compute all file name changes that occur going from checkin iFrom
   353         -** to checkin iTo.
   354         -**
   355         -** The number of name changes is written into *pnChng.  For each name
   356         -** change, two integers are allocated for *piChng.  The first is the 
   357         -** filename.fnid for the original name and the second is for new name.
   358         -** Space to hold *piChng is obtained from fossil_malloc() and should
   359         -** be released by the caller.
   360         -**
   361         -** This routine really has nothing to do with bisection.  It is located
   362         -** in this bisect.c module in order to leverage some of the bisect
   363         -** infrastructure.
   364         -*/
   365         -void find_filename_changes(
   366         -  int iFrom,
   367         -  int iTo,
   368         -  int *pnChng,
   369         -  int **aiChng
   370         -){
   371         -  BisectNode *p;           /* For looping over path from iFrom to iTo */
   372         -  NameChange *pAll = 0;    /* List of all name changes seen so far */
   373         -  NameChange *pChng;       /* For looping through the name change list */
   374         -  int nChng = 0;           /* Number of files whose names have changed */
   375         -  int *aChng;              /* Two integers per name change */
   376         -  int i;                   /* Loop counter */
   377         -  Stmt q1;                 /* Query of name changes */
   378         -
   379         -  *pnChng = 0;
   380         -  *aiChng = 0;
   381         -  bisect_reset();
   382         -  p = bisect_shortest_path(iFrom, iTo, 0);
   383         -  if( p==0 ) return;
   384         -  bisect_reverse_path();
   385         -  db_prepare(&q1,
   386         -     "SELECT pfnid, fnid FROM mlink WHERE mid=:mid AND pfnid>0"
   387         -  );
   388         -  for(p=bisect.pStart; p; p=p->u.pTo){
   389         -    int fnid, pfnid;
   390         -    if( !p->fromIsParent && (p->u.pTo==0 || p->u.pTo->fromIsParent) ){
   391         -      /* Skip nodes where the parent is not on the path */
   392         -      continue;
   393         -    }
   394         -    db_bind_int(&q1, ":mid", p->rid);
   395         -    while( db_step(&q1)==SQLITE_ROW ){
   396         -      if( p->fromIsParent ){
   397         -        fnid = db_column_int(&q1, 1);
   398         -        pfnid = db_column_int(&q1, 0);
   399         -      }else{
   400         -        fnid = db_column_int(&q1, 0);
   401         -        pfnid = db_column_int(&q1, 1);
   402         -      }
   403         -      for(pChng=pAll; pChng; pChng=pChng->pNext){
   404         -        if( pChng->curName==pfnid ){
   405         -          pChng->newName = fnid;
   406         -          break;
   407         -        }
   408         -      }
   409         -      if( pChng==0 ){
   410         -        pChng = fossil_malloc( sizeof(*pChng) );
   411         -        pChng->pNext = pAll;
   412         -        pAll = pChng;
   413         -        pChng->origName = pfnid;
   414         -        pChng->curName = pfnid;
   415         -        pChng->newName = fnid;
   416         -        nChng++;
   417         -      }
   418         -    }
   419         -    for(pChng=pAll; pChng; pChng=pChng->pNext) pChng->curName = pChng->newName;
   420         -    db_reset(&q1);
   421         -  }
   422         -  db_finalize(&q1);
   423         -  if( nChng ){
   424         -    *pnChng = nChng;
   425         -    aChng = *aiChng = fossil_malloc( nChng*2*sizeof(int) );
   426         -    for(pChng=pAll, i=0; pChng; pChng=pChng->pNext, i+=2){
   427         -      aChng[i] = pChng->origName;
   428         -      aChng[i+1] = pChng->newName;
   429         -    }
   430         -    while( pAll ){
   431         -      pChng = pAll;
   432         -      pAll = pAll->pNext;
   433         -      fossil_free(pChng);
   434         -    }
   435         -  }
   436         -}
   437         -
   438         -/*
   439         -** COMMAND: test-name-changes
   440         -**
   441         -** Usage: %fossil test-name-changes VERSION1 VERSION2
   442         -**
   443         -** Show all filename changes that occur going from VERSION1 to VERSION2
   444         -*/
   445         -void test_name_change(void){
   446         -  int iFrom;
   447         -  int iTo;
   448         -  int *aChng;
   449         -  int nChng;
   450         -  int i;
   451         -
   452         -  db_find_and_open_repository(0,0);
   453         -  if( g.argc!=4 ) usage("VERSION1 VERSION2");
   454         -  iFrom = name_to_rid(g.argv[2]);
   455         -  iTo = name_to_rid(g.argv[3]);
   456         -  find_filename_changes(iFrom, iTo, &nChng, &aChng);
   457         -  for(i=0; i<nChng; i++){
   458         -    char *zFrom, *zTo;
   459         -
   460         -    zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
   461         -    zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
   462         -    printf("[%s] -> [%s]\n", zFrom, zTo);
   463         -    fossil_free(zFrom);
   464         -    fossil_free(zTo);
   465         -  }
   466         -  fossil_free(aChng);
   467         -}

Changes to src/descendants.c.

   160    160   */
   161    161   void compute_ancestors(int rid, int N){
   162    162     Bag seen;
   163    163     PQueue queue;
   164    164     bag_init(&seen);
   165    165     pqueue_init(&queue);
   166    166     bag_insert(&seen, rid);
   167         -  pqueue_insert(&queue, rid, 0.0);
   168         -  while( (N--)>0 && (rid = pqueue_extract(&queue))!=0 ){
          167  +  pqueue_insert(&queue, rid, 0.0, 0);
          168  +  while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
   169    169       Stmt q;
   170    170       db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid);
   171    171       db_prepare(&q,
   172    172          "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid"
   173    173          " WHERE a.cid=%d", rid
   174    174       );
   175    175       while( db_step(&q)==SQLITE_ROW ){
   176    176         int pid = db_column_int(&q, 0);
   177    177         double mtime = db_column_double(&q, 1);
   178    178         if( bag_insert(&seen, pid) ){
   179         -        pqueue_insert(&queue, pid, -mtime);
          179  +        pqueue_insert(&queue, pid, -mtime, 0);
   180    180         }
   181    181       }
   182    182       db_finalize(&q);
   183    183     }
   184    184     bag_clear(&seen);
   185    185     pqueue_clear(&queue);
   186    186   }
................................................................................
   191    191   */
   192    192   void compute_descendants(int rid, int N){
   193    193     Bag seen;
   194    194     PQueue queue;
   195    195     bag_init(&seen);
   196    196     pqueue_init(&queue);
   197    197     bag_insert(&seen, rid);
   198         -  pqueue_insert(&queue, rid, 0.0);
   199         -  while( (N--)>0 && (rid = pqueue_extract(&queue))!=0 ){
          198  +  pqueue_insert(&queue, rid, 0.0, 0);
          199  +  while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){
   200    200       Stmt q;
   201    201       db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid);
   202    202       db_prepare(&q,"SELECT cid, mtime FROM plink WHERE pid=%d", rid);
   203    203       while( db_step(&q)==SQLITE_ROW ){
   204    204         int pid = db_column_int(&q, 0);
   205    205         double mtime = db_column_double(&q, 1);
   206    206         if( bag_insert(&seen, pid) ){
   207         -        pqueue_insert(&queue, pid, mtime);
          207  +        pqueue_insert(&queue, pid, mtime, 0);
   208    208         }
   209    209       }
   210    210       db_finalize(&q);
   211    211     }
   212    212     bag_clear(&seen);
   213    213     pqueue_clear(&queue);
   214    214   }

Changes to src/main.mk.

    52     52     $(SRCDIR)/login.c \
    53     53     $(SRCDIR)/main.c \
    54     54     $(SRCDIR)/manifest.c \
    55     55     $(SRCDIR)/md5.c \
    56     56     $(SRCDIR)/merge.c \
    57     57     $(SRCDIR)/merge3.c \
    58     58     $(SRCDIR)/name.c \
           59  +  $(SRCDIR)/path.c \
    59     60     $(SRCDIR)/pivot.c \
    60     61     $(SRCDIR)/popen.c \
    61     62     $(SRCDIR)/pqueue.c \
    62     63     $(SRCDIR)/printf.c \
    63     64     $(SRCDIR)/rebuild.c \
    64     65     $(SRCDIR)/report.c \
    65     66     $(SRCDIR)/rss.c \
................................................................................
   134    135     $(OBJDIR)/login_.c \
   135    136     $(OBJDIR)/main_.c \
   136    137     $(OBJDIR)/manifest_.c \
   137    138     $(OBJDIR)/md5_.c \
   138    139     $(OBJDIR)/merge_.c \
   139    140     $(OBJDIR)/merge3_.c \
   140    141     $(OBJDIR)/name_.c \
          142  +  $(OBJDIR)/path_.c \
   141    143     $(OBJDIR)/pivot_.c \
   142    144     $(OBJDIR)/popen_.c \
   143    145     $(OBJDIR)/pqueue_.c \
   144    146     $(OBJDIR)/printf_.c \
   145    147     $(OBJDIR)/rebuild_.c \
   146    148     $(OBJDIR)/report_.c \
   147    149     $(OBJDIR)/rss_.c \
................................................................................
   216    218    $(OBJDIR)/login.o \
   217    219    $(OBJDIR)/main.o \
   218    220    $(OBJDIR)/manifest.o \
   219    221    $(OBJDIR)/md5.o \
   220    222    $(OBJDIR)/merge.o \
   221    223    $(OBJDIR)/merge3.o \
   222    224    $(OBJDIR)/name.o \
          225  + $(OBJDIR)/path.o \
   223    226    $(OBJDIR)/pivot.o \
   224    227    $(OBJDIR)/popen.o \
   225    228    $(OBJDIR)/pqueue.o \
   226    229    $(OBJDIR)/printf.o \
   227    230    $(OBJDIR)/rebuild.o \
   228    231    $(OBJDIR)/report.o \
   229    232    $(OBJDIR)/rss.o \
................................................................................
   302    305   clean:	
   303    306   	rm -rf $(OBJDIR)/* $(APPNAME)
   304    307   
   305    308   
   306    309   $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
   307    310   	$(OBJDIR)/mkindex $(TRANS_SRC) >$@
   308    311   $(OBJDIR)/headers:	$(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
   309         -	$(OBJDIR)/makeheaders  $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
          312  +	$(OBJDIR)/makeheaders  $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
   310    313   	touch $(OBJDIR)/headers
   311    314   $(OBJDIR)/headers: Makefile
   312    315   Makefile:
   313    316   $(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(OBJDIR)/translate
   314    317   	$(OBJDIR)/translate $(SRCDIR)/add.c >$(OBJDIR)/add_.c
   315    318   
   316    319   $(OBJDIR)/add.o:	$(OBJDIR)/add_.c $(OBJDIR)/add.h  $(SRCDIR)/config.h
................................................................................
   621    624   $(OBJDIR)/name_.c:	$(SRCDIR)/name.c $(OBJDIR)/translate
   622    625   	$(OBJDIR)/translate $(SRCDIR)/name.c >$(OBJDIR)/name_.c
   623    626   
   624    627   $(OBJDIR)/name.o:	$(OBJDIR)/name_.c $(OBJDIR)/name.h  $(SRCDIR)/config.h
   625    628   	$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
   626    629   
   627    630   $(OBJDIR)/name.h:	$(OBJDIR)/headers
          631  +$(OBJDIR)/path_.c:	$(SRCDIR)/path.c $(OBJDIR)/translate
          632  +	$(OBJDIR)/translate $(SRCDIR)/path.c >$(OBJDIR)/path_.c
          633  +
          634  +$(OBJDIR)/path.o:	$(OBJDIR)/path_.c $(OBJDIR)/path.h  $(SRCDIR)/config.h
          635  +	$(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c
          636  +
          637  +$(OBJDIR)/path.h:	$(OBJDIR)/headers
   628    638   $(OBJDIR)/pivot_.c:	$(SRCDIR)/pivot.c $(OBJDIR)/translate
   629    639   	$(OBJDIR)/translate $(SRCDIR)/pivot.c >$(OBJDIR)/pivot_.c
   630    640   
   631    641   $(OBJDIR)/pivot.o:	$(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h  $(SRCDIR)/config.h
   632    642   	$(XTCC) -o $(OBJDIR)/pivot.o -c $(OBJDIR)/pivot_.c
   633    643   
   634    644   $(OBJDIR)/pivot.h:	$(OBJDIR)/headers

Changes to src/makemake.tcl.

    58     58     login
    59     59     main
    60     60     manifest
    61     61     md5
    62     62     merge
    63     63     merge3
    64     64     name
           65  +  path
    65     66     pivot
    66     67     popen
    67     68     pqueue
    68     69     printf
    69     70     rebuild
    70     71     report
    71     72     rss

Changes to src/name.c.

   145    145   */
   146    146   char *tag_to_uuid(const char *zTag){
   147    147     int vid;
   148    148     char *zUuid = 
   149    149       db_text(0,
   150    150          "SELECT blob.uuid"
   151    151          "  FROM tag, tagxref, event, blob"
   152         -       " WHERE tag.tagname='sym-'||%Q "
          152  +       " WHERE tag.tagname='sym-%q' "
   153    153          "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
   154    154          "   AND event.objid=tagxref.rid "
   155    155          "   AND blob.rid=event.objid "
   156    156          " ORDER BY event.mtime DESC ",
   157    157          zTag
   158    158       );
   159    159     if( zUuid==0 ){
................................................................................
   169    169             nDate -= 3;
   170    170             zDate[nDate] = 0;
   171    171             useUtc = 1;
   172    172           }
   173    173           zUuid = db_text(0,
   174    174             "SELECT blob.uuid"
   175    175             "  FROM tag, tagxref, event, blob"
   176         -          " WHERE tag.tagname='sym-'||%Q "
          176  +          " WHERE tag.tagname='sym-%q' "
   177    177             "   AND tagxref.tagid=tag.tagid AND tagxref.tagtype>0 "
   178    178             "   AND event.objid=tagxref.rid "
   179    179             "   AND blob.rid=event.objid "
   180    180             "   AND event.mtime<=julianday(%Q %s)"
   181    181             " ORDER BY event.mtime DESC ",
   182    182             zTagBase, zDate, (useUtc ? "" : ",'utc'")
   183    183           );

Added src/path.c.

            1  +/*
            2  +** Copyright (c) 2011 D. Richard Hipp
            3  +**
            4  +** This program is free software; you can redistribute it and/or
            5  +** modify it under the terms of the Simplified BSD License (also
            6  +** known as the "2-Clause License" or "FreeBSD License".)
            7  +
            8  +** This program is distributed in the hope that it will be useful,
            9  +** but without any warranty; without even the implied warranty of
           10  +** merchantability or fitness for a particular purpose.
           11  +**
           12  +** Author contact information:
           13  +**   drh@sqlite.org
           14  +**
           15  +*******************************************************************************
           16  +**
           17  +** This file contains code used to trace paths of through the
           18  +** directed acyclic graph (DAG) of checkins.
           19  +*/
           20  +#include "config.h"
           21  +#include "path.h"
           22  +#include <assert.h>
           23  +
           24  +#if INTERFACE
           25  +/* Nodes for the paths through the DAG.
           26  +*/
           27  +struct PathNode {
           28  +  int rid;                 /* ID for this node */
           29  +  u8 fromIsParent;         /* True if pFrom is the parent of rid */
           30  +  u8 isPrim;               /* True if primary side of common ancestor */
           31  +  PathNode *pFrom;         /* Node we came from */
           32  +  union {
           33  +    PathNode *pPeer;       /* List of nodes of the same generation */
           34  +    PathNode *pTo;         /* Next on path from beginning to end */
           35  +  } u;
           36  +  PathNode *pAll;        /* List of all nodes */
           37  +};
           38  +#endif
           39  +
           40  +/*
           41  +** Local variables for this module
           42  +*/
           43  +static struct {
           44  +  PathNode *pCurrent;   /* Current generation of nodes */
           45  +  PathNode *pAll;       /* All nodes */
           46  +  Bag seen;             /* Nodes seen before */
           47  +  int nStep;            /* Number of steps from first to last */
           48  +  PathNode *pStart;     /* Earliest node */
           49  +  PathNode *pPivot;     /* Common ancestor of pStart and pEnd */
           50  +  PathNode *pEnd;       /* Most recent */
           51  +} path;
           52  +
           53  +/*
           54  +** Return the first (last) element of the computed path.
           55  +*/
           56  +PathNode *path_first(void){ return path.pStart; }
           57  +PathNode *path_last(void){ return path.pEnd; }
           58  +
           59  +/*
           60  +** Return the number of steps in the computed path.
           61  +*/
           62  +int path_length(void){ return path.nStep; }
           63  +
           64  +/*
           65  +** Create a new node
           66  +*/
           67  +static PathNode *path_new_node(int rid, PathNode *pFrom, int isParent){
           68  +  PathNode *p;
           69  +
           70  +  p = fossil_malloc( sizeof(*p) );
           71  +  memset(p, 0, sizeof(*p));
           72  +  p->rid = rid;
           73  +  p->fromIsParent = isParent;
           74  +  p->pFrom = pFrom;
           75  +  p->u.pPeer = path.pCurrent;
           76  +  path.pCurrent = p;
           77  +  p->pAll = path.pAll;
           78  +  path.pAll = p;
           79  +  bag_insert(&path.seen, rid);
           80  +  return p;
           81  +}
           82  +
           83  +/*
           84  +** Reset memory used by the shortest path algorithm.
           85  +*/
           86  +void path_reset(void){
           87  +  PathNode *p;
           88  +  while( path.pAll ){
           89  +    p = path.pAll;
           90  +    path.pAll = p->pAll;
           91  +    fossil_free(p);
           92  +  }
           93  +  bag_clear(&path.seen);
           94  +  path.pCurrent = 0;
           95  +  path.pAll = 0;
           96  +  path.pEnd = 0;
           97  +  path.nStep = 0;
           98  +}
           99  +
          100  +/*
          101  +** Construct the path from path.pStart to path.pEnd in the u.pTo fields.
          102  +*/
          103  +void path_reverse_path(void){
          104  +  PathNode *p;
          105  +  for(p=path.pEnd; p && p->pFrom; p = p->pFrom){
          106  +    p->pFrom->u.pTo = p;
          107  +  }
          108  +  path.pEnd->u.pTo = 0;
          109  +  assert( p==path.pStart );
          110  +}
          111  +
          112  +/*
          113  +** Compute the shortest path from iFrom to iTo
          114  +**
          115  +** If directOnly is true, then use only the "primary" links from parent to
          116  +** child.  In other words, ignore merges.
          117  +**
          118  +** Return a pointer to the beginning of the path (the iFrom node).  
          119  +** Elements of the path can be traversed by following the PathNode.u.pTo
          120  +** pointer chain.
          121  +**
          122  +** Return NULL if no path is found.
          123  +*/
          124  +PathNode *path_shortest(int iFrom, int iTo, int directOnly){
          125  +  Stmt s;
          126  +  PathNode *pPrev;
          127  +  PathNode *p;
          128  +
          129  +  path_reset();
          130  +  path.pStart = path_new_node(iFrom, 0, 0);
          131  +  if( iTo==iFrom ) return path.pStart;
          132  +  if( directOnly ){
          133  +    db_prepare(&s, 
          134  +        "SELECT cid, 1 FROM plink WHERE pid=:pid AND isprim "
          135  +        "UNION ALL "
          136  +        "SELECT pid, 0 FROM plink WHERE cid=:pid AND isprim"
          137  +    );
          138  +  }else{
          139  +    db_prepare(&s, 
          140  +        "SELECT cid, 1 FROM plink WHERE pid=:pid "
          141  +        "UNION ALL "
          142  +        "SELECT pid, 0 FROM plink WHERE cid=:pid"
          143  +    );
          144  +  }
          145  +  while( path.pCurrent ){
          146  +    path.nStep++;
          147  +    pPrev = path.pCurrent;
          148  +    path.pCurrent = 0;
          149  +    while( pPrev ){
          150  +      db_bind_int(&s, ":pid", pPrev->rid);
          151  +      while( db_step(&s)==SQLITE_ROW ){
          152  +        int cid = db_column_int(&s, 0);
          153  +        int isParent = db_column_int(&s, 1);
          154  +        if( bag_find(&path.seen, cid) ) continue;
          155  +        p = path_new_node(cid, pPrev, isParent);
          156  +        if( cid==iTo ){
          157  +          db_finalize(&s);
          158  +          path.pEnd = p;
          159  +          path_reverse_path();
          160  +          return path.pStart;
          161  +        }
          162  +      }
          163  +      db_reset(&s);
          164  +      pPrev = pPrev->u.pPeer;
          165  +    }
          166  +  }
          167  +  db_finalize(&s);
          168  +  path_reset();
          169  +  return 0;
          170  +}
          171  +
          172  +/*
          173  +** Find the mid-point of the path.  If the path contains fewer than
          174  +** 2 steps, return 0.
          175  +*/
          176  +PathNode *path_midpoint(void){
          177  +  PathNode *p;
          178  +  int i;
          179  +  if( path.nStep<2 ) return 0;
          180  +  for(p=path.pEnd, i=0; p && i<path.nStep/2; p=p->pFrom, i++){}
          181  +  return p;
          182  +}
          183  +
          184  +/*
          185  +** COMMAND:  test-shortest-path
          186  +**
          187  +** Usage: %fossil test-shortest-path ?--no-merge? VERSION1 VERSION2
          188  +**
          189  +** Report the shortest path between two checkins.  If the --no-merge flag
          190  +** is used, follow only direct parent-child paths and omit merge links.
          191  +*/
          192  +void shortest_path_test_cmd(void){
          193  +  int iFrom;
          194  +  int iTo;
          195  +  PathNode *p;
          196  +  int n;
          197  +  int directOnly;
          198  +
          199  +  db_find_and_open_repository(0,0);
          200  +  directOnly = find_option("no-merge",0,0)!=0;
          201  +  if( g.argc!=4 ) usage("VERSION1 VERSION2");
          202  +  iFrom = name_to_rid(g.argv[2]);
          203  +  iTo = name_to_rid(g.argv[3]);
          204  +  p = path_shortest(iFrom, iTo, directOnly);
          205  +  if( p==0 ){
          206  +    fossil_fatal("no path from %s to %s", g.argv[1], g.argv[2]);
          207  +  }
          208  +  for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
          209  +    char *z;
          210  +    z = db_text(0,
          211  +      "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
          212  +      "  FROM blob, event"
          213  +      " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
          214  +      p->rid, p->rid);
          215  +    printf("%4d: %s", n, z);
          216  +    fossil_free(z);
          217  +    if( p->u.pTo ){
          218  +      printf(" is a %s of\n", p->u.pTo->fromIsParent ? "parent" : "child");
          219  +    }else{
          220  +      printf("\n");
          221  +    }
          222  +  }
          223  +}
          224  +
          225  +/*
          226  +** Find the closest common ancestor of two nodes.  "Closest" means the
          227  +** fewest number of arcs.
          228  +*/
          229  +int path_common_ancestor(int iMe, int iYou){
          230  +  Stmt s;
          231  +  PathNode *pPrev;
          232  +  PathNode *p;
          233  +  Bag me, you;
          234  +
          235  +  if( iMe==iYou ) return iMe;
          236  +  if( iMe==0 || iYou==0 ) return 0;
          237  +  path_reset();
          238  +  path.pStart = path_new_node(iMe, 0, 0);
          239  +  path.pStart->isPrim = 1;
          240  +  path.pEnd = path_new_node(iYou, 0, 0);
          241  +  db_prepare(&s, "SELECT pid FROM plink WHERE cid=:cid");
          242  +  bag_init(&me);
          243  +  bag_insert(&me, iMe);
          244  +  bag_init(&you);
          245  +  bag_insert(&you, iYou);
          246  +  while( path.pCurrent ){
          247  +    pPrev = path.pCurrent;
          248  +    path.pCurrent = 0;
          249  +    while( pPrev ){
          250  +      db_bind_int(&s, ":cid", pPrev->rid);
          251  +      while( db_step(&s)==SQLITE_ROW ){
          252  +        int pid = db_column_int(&s, 0);
          253  +        if( bag_find(pPrev->isPrim ? &you : &me, pid) ){
          254  +          /* pid is the common ancestor */
          255  +          PathNode *pNext;
          256  +          for(p=path.pAll; p && p->rid!=pid; p=p->pAll){}
          257  +          assert( p!=0 );
          258  +          pNext = p;
          259  +          while( pNext ){
          260  +            pNext = p->pFrom;
          261  +            p->pFrom = pPrev;
          262  +            pPrev = p;
          263  +            p = pNext;
          264  +          }
          265  +          if( pPrev==path.pStart ) path.pStart = path.pEnd;
          266  +          path.pEnd = pPrev;
          267  +          path_reverse_path();
          268  +          db_finalize(&s);
          269  +          return pid;
          270  +        }else if( bag_find(&path.seen, pid) ){
          271  +          /* pid is just an alternative path on one of the legs */
          272  +          continue;
          273  +        }
          274  +        p = path_new_node(pid, pPrev, 0);
          275  +        p->isPrim = pPrev->isPrim;
          276  +        bag_insert(pPrev->isPrim ? &me : &you, pid);
          277  +      }
          278  +      db_reset(&s);
          279  +      pPrev = pPrev->u.pPeer;
          280  +    }
          281  +  }
          282  +  db_finalize(&s);
          283  +  path_reset();
          284  +  return 0;
          285  +}
          286  +
          287  +/*
          288  +** COMMAND:  test-ancestor-path
          289  +**
          290  +** Usage: %fossil test-ancestor-path VERSION1 VERSION2
          291  +**
          292  +** Report the path from VERSION1 to VERSION2 through their most recent
          293  +** common ancestor.
          294  +*/
          295  +void ancestor_path_test_cmd(void){
          296  +  int iFrom;
          297  +  int iTo;
          298  +  int iPivot;
          299  +  PathNode *p;
          300  +  int n;
          301  +
          302  +  db_find_and_open_repository(0,0);
          303  +  if( g.argc!=4 ) usage("VERSION1 VERSION2");
          304  +  iFrom = name_to_rid(g.argv[2]);
          305  +  iTo = name_to_rid(g.argv[3]);
          306  +  iPivot = path_common_ancestor(iFrom, iTo);
          307  +  for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
          308  +    char *z;
          309  +    z = db_text(0,
          310  +      "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
          311  +      "  FROM blob, event"
          312  +      " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
          313  +      p->rid, p->rid);
          314  +    printf("%4d: %s", n, z);
          315  +    fossil_free(z);
          316  +    if( p->rid==iFrom ) printf(" VERSION1");
          317  +    if( p->rid==iTo ) printf(" VERSION2");
          318  +    if( p->rid==iPivot ) printf(" PIVOT");
          319  +    printf("\n");
          320  +  }
          321  +}
          322  +
          323  +
          324  +/*
          325  +** A record of a file rename operation.
          326  +*/
          327  +typedef struct NameChange NameChange;
          328  +struct NameChange {
          329  +  int origName;        /* Original name of file */
          330  +  int curName;         /* Current name of the file */
          331  +  int newName;         /* Name of file in next version */
          332  +  NameChange *pNext;   /* List of all name changes */
          333  +};
          334  +
          335  +/*
          336  +** Compute all file name changes that occur going from checkin iFrom
          337  +** to checkin iTo.
          338  +**
          339  +** The number of name changes is written into *pnChng.  For each name
          340  +** change, two integers are allocated for *piChng.  The first is the 
          341  +** filename.fnid for the original name and the second is for new name.
          342  +** Space to hold *piChng is obtained from fossil_malloc() and should
          343  +** be released by the caller.
          344  +**
          345  +** This routine really has nothing to do with pathion.  It is located
          346  +** in this path.c module in order to leverage some of the path
          347  +** infrastructure.
          348  +*/
          349  +void find_filename_changes(
          350  +  int iFrom,
          351  +  int iTo,
          352  +  int *pnChng,
          353  +  int **aiChng
          354  +){
          355  +  PathNode *p;           /* For looping over path from iFrom to iTo */
          356  +  NameChange *pAll = 0;    /* List of all name changes seen so far */
          357  +  NameChange *pChng;       /* For looping through the name change list */
          358  +  int nChng = 0;           /* Number of files whose names have changed */
          359  +  int *aChng;              /* Two integers per name change */
          360  +  int i;                   /* Loop counter */
          361  +  Stmt q1;                 /* Query of name changes */
          362  +
          363  +  *pnChng = 0;
          364  +  *aiChng = 0;
          365  +  path_reset();
          366  +  p = path_shortest(iFrom, iTo, 0);
          367  +  if( p==0 ) return;
          368  +  path_reverse_path();
          369  +  db_prepare(&q1,
          370  +     "SELECT pfnid, fnid FROM mlink WHERE mid=:mid AND pfnid>0"
          371  +  );
          372  +  for(p=path.pStart; p; p=p->u.pTo){
          373  +    int fnid, pfnid;
          374  +    if( !p->fromIsParent && (p->u.pTo==0 || p->u.pTo->fromIsParent) ){
          375  +      /* Skip nodes where the parent is not on the path */
          376  +      continue;
          377  +    }
          378  +    db_bind_int(&q1, ":mid", p->rid);
          379  +    while( db_step(&q1)==SQLITE_ROW ){
          380  +      if( p->fromIsParent ){
          381  +        fnid = db_column_int(&q1, 1);
          382  +        pfnid = db_column_int(&q1, 0);
          383  +      }else{
          384  +        fnid = db_column_int(&q1, 0);
          385  +        pfnid = db_column_int(&q1, 1);
          386  +      }
          387  +      for(pChng=pAll; pChng; pChng=pChng->pNext){
          388  +        if( pChng->curName==pfnid ){
          389  +          pChng->newName = fnid;
          390  +          break;
          391  +        }
          392  +      }
          393  +      if( pChng==0 ){
          394  +        pChng = fossil_malloc( sizeof(*pChng) );
          395  +        pChng->pNext = pAll;
          396  +        pAll = pChng;
          397  +        pChng->origName = pfnid;
          398  +        pChng->curName = pfnid;
          399  +        pChng->newName = fnid;
          400  +        nChng++;
          401  +      }
          402  +    }
          403  +    for(pChng=pAll; pChng; pChng=pChng->pNext) pChng->curName = pChng->newName;
          404  +    db_reset(&q1);
          405  +  }
          406  +  db_finalize(&q1);
          407  +  if( nChng ){
          408  +    *pnChng = nChng;
          409  +    aChng = *aiChng = fossil_malloc( nChng*2*sizeof(int) );
          410  +    for(pChng=pAll, i=0; pChng; pChng=pChng->pNext, i+=2){
          411  +      aChng[i] = pChng->origName;
          412  +      aChng[i+1] = pChng->newName;
          413  +    }
          414  +    while( pAll ){
          415  +      pChng = pAll;
          416  +      pAll = pAll->pNext;
          417  +      fossil_free(pChng);
          418  +    }
          419  +  }
          420  +}
          421  +
          422  +/*
          423  +** COMMAND: test-name-changes
          424  +**
          425  +** Usage: %fossil test-name-changes VERSION1 VERSION2
          426  +**
          427  +** Show all filename changes that occur going from VERSION1 to VERSION2
          428  +*/
          429  +void test_name_change(void){
          430  +  int iFrom;
          431  +  int iTo;
          432  +  int *aChng;
          433  +  int nChng;
          434  +  int i;
          435  +
          436  +  db_find_and_open_repository(0,0);
          437  +  if( g.argc!=4 ) usage("VERSION1 VERSION2");
          438  +  iFrom = name_to_rid(g.argv[2]);
          439  +  iTo = name_to_rid(g.argv[3]);
          440  +  find_filename_changes(iFrom, iTo, &nChng, &aChng);
          441  +  for(i=0; i<nChng; i++){
          442  +    char *zFrom, *zTo;
          443  +
          444  +    zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
          445  +    zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
          446  +    printf("[%s] -> [%s]\n", zFrom, zTo);
          447  +    fossil_free(zFrom);
          448  +    fossil_free(zTo);
          449  +  }
          450  +  fossil_free(aChng);
          451  +}

Changes to src/pqueue.c.

    36     36   ** Integers must be positive.
    37     37   */
    38     38   struct PQueue {
    39     39     int cnt;   /* Number of entries in the queue */
    40     40     int sz;    /* Number of slots in a[] */
    41     41     struct QueueElement {
    42     42       int id;          /* ID of the element */
           43  +    void *p;         /* Content pointer */
    43     44       double value;    /* Value of element.  Kept in ascending order */
    44     45     } *a;
    45     46   };
    46     47   #endif
    47     48   
    48     49   /*
    49     50   ** Initialize a PQueue structure
................................................................................
    67     68     p->a = fossil_realloc(p->a, sizeof(p->a[0])*N);
    68     69     p->sz = N;
    69     70   }
    70     71   
    71     72   /*
    72     73   ** Insert element e into the queue.
    73     74   */
    74         -void pqueue_insert(PQueue *p, int e, double v){
           75  +void pqueue_insert(PQueue *p, int e, double v, void *pData){
    75     76     int i, j;
    76     77     if( p->cnt+1>p->sz ){
    77     78       pqueue_resize(p, p->cnt+5);
    78     79     }
    79     80     for(i=0; i<p->cnt; i++){
    80     81       if( p->a[i].value>v ){
    81     82         for(j=p->cnt; j>i; j--){
    82     83           p->a[j] = p->a[j-1];
    83     84         }
    84     85         break;
    85     86       }
    86     87     }
    87     88     p->a[i].id = e;
           89  +  p->a[i].p = pData;
    88     90     p->a[i].value = v;
    89     91     p->cnt++;
    90     92   }
    91     93   
    92     94   /*
    93     95   ** Extract the first element from the queue (the element with
    94     96   ** the smallest value) and return its ID.  Return 0 if the queue
    95     97   ** is empty.
    96     98   */
    97         -int pqueue_extract(PQueue *p){
           99  +int pqueue_extract(PQueue *p, void **pp){
    98    100     int e, i;
    99    101     if( p->cnt==0 ){
          102  +    if( pp ) *pp = 0;
   100    103       return 0;
   101    104     }
   102    105     e = p->a[0].id;
          106  +  if( pp ) *pp = p->a[0].p;
   103    107     for(i=0; i<p->cnt-1; i++){
   104    108       p->a[i] = p->a[i+1];
   105    109     }
   106    110     p->cnt--;
   107    111     return e;
   108    112   }

Changes to src/tag.c.

    42     42     PQueue queue;        /* Queue of check-ins to be tagged */
    43     43     Stmt s;              /* Query the children of :pid to which to propagate */
    44     44     Stmt ins;            /* INSERT INTO tagxref */
    45     45     Stmt eventupdate;    /* UPDATE event */
    46     46   
    47     47     assert( tagType==0 || tagType==2 );
    48     48     pqueue_init(&queue);
    49         -  pqueue_insert(&queue, pid, 0.0);
           49  +  pqueue_insert(&queue, pid, 0.0, 0);
    50     50   
    51     51     /* Query for children of :pid to which to propagate the tag.
    52     52     ** Three returns:  (1) rid of the child.  (2) timestamp of child.
    53     53     ** (3) True to propagate or false to block.
    54     54     */
    55     55     db_prepare(&s, 
    56     56        "SELECT cid, plink.mtime,"
................................................................................
    77     77       );
    78     78     }
    79     79     if( tagid==TAG_BGCOLOR ){
    80     80       db_prepare(&eventupdate,
    81     81         "UPDATE event SET bgcolor=%Q WHERE objid=:rid", zValue
    82     82       );
    83     83     }
    84         -  while( (pid = pqueue_extract(&queue))!=0 ){
           84  +  while( (pid = pqueue_extract(&queue, 0))!=0 ){
    85     85       db_bind_int(&s, ":pid", pid);
    86     86       while( db_step(&s)==SQLITE_ROW ){
    87     87         int doit = db_column_int(&s, 2);
    88     88         if( doit ){
    89     89           int cid = db_column_int(&s, 0);
    90     90           double mtime = db_column_double(&s, 1);
    91         -        pqueue_insert(&queue, cid, mtime);
           91  +        pqueue_insert(&queue, cid, mtime, 0);
    92     92           db_bind_int(&ins, ":rid", cid);
    93     93           db_step(&ins);
    94     94           db_reset(&ins);
    95     95           if( tagid==TAG_BGCOLOR ){
    96     96             db_bind_int(&eventupdate, ":rid", cid);
    97     97             db_step(&eventupdate);
    98     98             db_reset(&eventupdate);

Changes to src/timeline.c.

   761    761     int tmFlags;                       /* Timeline flags */
   762    762     const char *zThisTag = 0;          /* Suppress links to this tag */
   763    763     const char *zThisUser = 0;         /* Suppress links to this user */
   764    764     HQuery url;                        /* URL for various branch links */
   765    765     int from_rid = name_to_rid(P("from"));  /* from= for path timelines */
   766    766     int to_rid = name_to_rid(P("to"));      /* to= for path timelines */
   767    767     int noMerge = P("nomerge")!=0;          /* Do not follow merge links */
          768  +  int me_rid = name_to_rid(P("me"));    /* me= for common ancestory path */
          769  +  int you_rid = name_to_rid(P("you"));/* you= for common ancst path */
   768    770   
   769    771     /* To view the timeline, must have permission to read project data.
   770    772     */
   771    773     login_check_credentials();
   772    774     if( !g.okRead && !g.okRdTkt && !g.okRdWiki ){ login_needed(); return; }
   773    775     if( zTagName && g.okRead ){
   774    776       tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName);
................................................................................
   793    795     timeline_temp_table();
   794    796     blob_zero(&sql);
   795    797     blob_zero(&desc);
   796    798     blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
   797    799     blob_append(&sql, timeline_query_for_www(), -1);
   798    800     url_initialize(&url, "timeline");
   799    801     if( !useDividers ) url_add_parameter(&url, "nd", 0);
   800         -  if( from_rid && to_rid && g.okRead ){
          802  +  if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.okRead ){
   801    803       /* If from= and to= are present, display all nodes on a path connecting
   802    804       ** the two */
   803         -    BisectNode *p;
   804         -    const char *z;
          805  +    PathNode *p = 0;
          806  +    const char *zFrom = 0;
          807  +    const char *zTo = 0;
   805    808   
   806         -    bisect_shortest_path(from_rid, to_rid, noMerge);
   807         -    p = bisect_reverse_path();
          809  +    if( from_rid && to_rid ){
          810  +      p = path_shortest(from_rid, to_rid, noMerge);
          811  +      zFrom = P("from");
          812  +      zTo = P("to");
          813  +    }else{
          814  +      if( path_common_ancestor(me_rid, you_rid) ){
          815  +        p = path_first();
          816  +      }
          817  +      zFrom = P("me");
          818  +      zTo = P("you");
          819  +    }
   808    820       blob_append(&sql, " AND event.objid IN (0", -1);
   809    821       while( p ){
   810    822         blob_appendf(&sql, ",%d", p->rid);
   811    823         p = p->u.pTo;
   812    824       }
   813    825       blob_append(&sql, ")", -1);
   814         -    bisect_reset();
          826  +    path_reset();
   815    827       blob_append(&desc, "All nodes on the path from ", -1);
   816         -    z = P("from");
   817    828       if( g.okHistory ){
   818         -      blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>",  g.zTop, z, z);
          829  +      blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>",  g.zTop,zFrom,zFrom);
   819    830       }else{
   820         -      blob_appendf(&desc, "[%h]", z);
          831  +      blob_appendf(&desc, "[%h]", zFrom);
   821    832       }
   822    833       blob_append(&desc, " and ", -1);
   823         -    z = P("to");
   824    834       if( g.okHistory ){
   825         -      blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>.",  g.zTop, z, z);
          835  +      blob_appendf(&desc, "<a href='%s/info/%h'>[%h]</a>.",  g.zTop, zTo, zTo);
   826    836       }else{
   827         -      blob_appendf(&desc, "[%h].", z);
          837  +      blob_appendf(&desc, "[%h].", zTo);
   828    838       }
   829    839       tmFlags |= TIMELINE_DISJOINT;
   830    840       db_multi_exec("%s", blob_str(&sql));
   831    841     }else if( (p_rid || d_rid) && g.okRead ){
   832    842       /* If p= or d= is present, ignore all other parameters other than n= */
   833    843       char *zUuid;
   834    844       int np, nd;

Changes to win/Makefile.dmc.

    22     22   CFLAGS = -o
    23     23   BCC    = $(DMDIR)\bin\dmc $(CFLAGS)
    24     24   TCC    = $(DMDIR)\bin\dmc $(CFLAGS) $(DMCDEF) $(I18N) $(SSL) $(INCL)
    25     25   LIBS   = $(DMDIR)\extra\lib\ zlib wsock32
    26     26   
    27     27   SQLITE_OPTIONS = -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_STAT2 -Dlocaltime=fossil_localtime -DSQLITE_ENABLE_LOCKING_STYLE=0
    28     28   
    29         -SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c 
           29  +SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c 
    30     30   
    31         -OBJ   = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O 
           31  +OBJ   = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\leaf$O $(OBJDIR)\login$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\rebuild$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winhttp$O $(OBJDIR)\xfer$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O 
    32     32   
    33     33   
    34     34   RC=$(DMDIR)\bin\rcc
    35     35   RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
    36     36   
    37     37   APPNAME = $(OBJDIR)\fossil$(E)
    38     38   
................................................................................
    42     42   	cd $(OBJDIR) 
    43     43   	$(DMDIR)\bin\link @link
    44     44   
    45     45   $(OBJDIR)\fossil.res:	$B\win\fossil.rc
    46     46   	$(RC) $(RCFLAGS) -o$@ $**
    47     47   
    48     48   $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
    49         -	+echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip shell sqlite3 th th_lang > $@
           49  +	+echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip shell sqlite3 th th_lang > $@
    50     50   	+echo fossil >> $@
    51     51   	+echo fossil >> $@
    52     52   	+echo $(LIBS) >> $@
    53     53   	+echo. >> $@
    54     54   	+echo fossil >> $@
    55     55   
    56     56   translate$E: $(SRCDIR)\translate.c
................................................................................
   356    356   	+translate$E $** > $@
   357    357   
   358    358   $(OBJDIR)\name$O : name_.c name.h
   359    359   	$(TCC) -o$@ -c name_.c
   360    360   
   361    361   name_.c : $(SRCDIR)\name.c
   362    362   	+translate$E $** > $@
          363  +
          364  +$(OBJDIR)\path$O : path_.c path.h
          365  +	$(TCC) -o$@ -c path_.c
          366  +
          367  +path_.c : $(SRCDIR)\path.c
          368  +	+translate$E $** > $@
   363    369   
   364    370   $(OBJDIR)\pivot$O : pivot_.c pivot.h
   365    371   	$(TCC) -o$@ -c pivot_.c
   366    372   
   367    373   pivot_.c : $(SRCDIR)\pivot.c
   368    374   	+translate$E $** > $@
   369    375   
................................................................................
   568    574   $(OBJDIR)\zip$O : zip_.c zip.h
   569    575   	$(TCC) -o$@ -c zip_.c
   570    576   
   571    577   zip_.c : $(SRCDIR)\zip.c
   572    578   	+translate$E $** > $@
   573    579   
   574    580   headers: makeheaders$E page_index.h VERSION.h
   575         -	 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
          581  +	 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
   576    582   	@copy /Y nul: headers

Changes to win/Makefile.mingw.

   115    115     $(SRCDIR)/login.c \
   116    116     $(SRCDIR)/main.c \
   117    117     $(SRCDIR)/manifest.c \
   118    118     $(SRCDIR)/md5.c \
   119    119     $(SRCDIR)/merge.c \
   120    120     $(SRCDIR)/merge3.c \
   121    121     $(SRCDIR)/name.c \
          122  +  $(SRCDIR)/path.c \
   122    123     $(SRCDIR)/pivot.c \
   123    124     $(SRCDIR)/popen.c \
   124    125     $(SRCDIR)/pqueue.c \
   125    126     $(SRCDIR)/printf.c \
   126    127     $(SRCDIR)/rebuild.c \
   127    128     $(SRCDIR)/report.c \
   128    129     $(SRCDIR)/rss.c \
................................................................................
   197    198     $(OBJDIR)/login_.c \
   198    199     $(OBJDIR)/main_.c \
   199    200     $(OBJDIR)/manifest_.c \
   200    201     $(OBJDIR)/md5_.c \
   201    202     $(OBJDIR)/merge_.c \
   202    203     $(OBJDIR)/merge3_.c \
   203    204     $(OBJDIR)/name_.c \
          205  +  $(OBJDIR)/path_.c \
   204    206     $(OBJDIR)/pivot_.c \
   205    207     $(OBJDIR)/popen_.c \
   206    208     $(OBJDIR)/pqueue_.c \
   207    209     $(OBJDIR)/printf_.c \
   208    210     $(OBJDIR)/rebuild_.c \
   209    211     $(OBJDIR)/report_.c \
   210    212     $(OBJDIR)/rss_.c \
................................................................................
   279    281    $(OBJDIR)/login.o \
   280    282    $(OBJDIR)/main.o \
   281    283    $(OBJDIR)/manifest.o \
   282    284    $(OBJDIR)/md5.o \
   283    285    $(OBJDIR)/merge.o \
   284    286    $(OBJDIR)/merge3.o \
   285    287    $(OBJDIR)/name.o \
          288  + $(OBJDIR)/path.o \
   286    289    $(OBJDIR)/pivot.o \
   287    290    $(OBJDIR)/popen.o \
   288    291    $(OBJDIR)/pqueue.o \
   289    292    $(OBJDIR)/printf.o \
   290    293    $(OBJDIR)/rebuild.o \
   291    294    $(OBJDIR)/report.o \
   292    295    $(OBJDIR)/rss.o \
................................................................................
   380    383   setup: $(OBJDIR) $(APPNAME)
   381    384   	$(MAKENSIS) ./fossil.nsi
   382    385   
   383    386   
   384    387   $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
   385    388   	$(MKINDEX) $(TRANS_SRC) >$@
   386    389   $(OBJDIR)/headers:	$(OBJDIR)/page_index.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
   387         -	$(MAKEHEADERS)  $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
          390  +	$(MAKEHEADERS)  $(OBJDIR)/add_.c:$(OBJDIR)/add.h $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h $(OBJDIR)/bag_.c:$(OBJDIR)/bag.h $(OBJDIR)/bisect_.c:$(OBJDIR)/bisect.h $(OBJDIR)/blob_.c:$(OBJDIR)/blob.h $(OBJDIR)/branch_.c:$(OBJDIR)/branch.h $(OBJDIR)/browse_.c:$(OBJDIR)/browse.h $(OBJDIR)/captcha_.c:$(OBJDIR)/captcha.h $(OBJDIR)/cgi_.c:$(OBJDIR)/cgi.h $(OBJDIR)/checkin_.c:$(OBJDIR)/checkin.h $(OBJDIR)/checkout_.c:$(OBJDIR)/checkout.h $(OBJDIR)/clearsign_.c:$(OBJDIR)/clearsign.h $(OBJDIR)/clone_.c:$(OBJDIR)/clone.h $(OBJDIR)/comformat_.c:$(OBJDIR)/comformat.h $(OBJDIR)/configure_.c:$(OBJDIR)/configure.h $(OBJDIR)/content_.c:$(OBJDIR)/content.h $(OBJDIR)/db_.c:$(OBJDIR)/db.h $(OBJDIR)/delta_.c:$(OBJDIR)/delta.h $(OBJDIR)/deltacmd_.c:$(OBJDIR)/deltacmd.h $(OBJDIR)/descendants_.c:$(OBJDIR)/descendants.h $(OBJDIR)/diff_.c:$(OBJDIR)/diff.h $(OBJDIR)/diffcmd_.c:$(OBJDIR)/diffcmd.h $(OBJDIR)/doc_.c:$(OBJDIR)/doc.h $(OBJDIR)/encode_.c:$(OBJDIR)/encode.h $(OBJDIR)/event_.c:$(OBJDIR)/event.h $(OBJDIR)/export_.c:$(OBJDIR)/export.h $(OBJDIR)/file_.c:$(OBJDIR)/file.h $(OBJDIR)/finfo_.c:$(OBJDIR)/finfo.h $(OBJDIR)/graph_.c:$(OBJDIR)/graph.h $(OBJDIR)/gzip_.c:$(OBJDIR)/gzip.h $(OBJDIR)/http_.c:$(OBJDIR)/http.h $(OBJDIR)/http_socket_.c:$(OBJDIR)/http_socket.h $(OBJDIR)/http_ssl_.c:$(OBJDIR)/http_ssl.h $(OBJDIR)/http_transport_.c:$(OBJDIR)/http_transport.h $(OBJDIR)/import_.c:$(OBJDIR)/import.h $(OBJDIR)/info_.c:$(OBJDIR)/info.h $(OBJDIR)/leaf_.c:$(OBJDIR)/leaf.h $(OBJDIR)/login_.c:$(OBJDIR)/login.h $(OBJDIR)/main_.c:$(OBJDIR)/main.h $(OBJDIR)/manifest_.c:$(OBJDIR)/manifest.h $(OBJDIR)/md5_.c:$(OBJDIR)/md5.h $(OBJDIR)/merge_.c:$(OBJDIR)/merge.h $(OBJDIR)/merge3_.c:$(OBJDIR)/merge3.h $(OBJDIR)/name_.c:$(OBJDIR)/name.h $(OBJDIR)/path_.c:$(OBJDIR)/path.h $(OBJDIR)/pivot_.c:$(OBJDIR)/pivot.h $(OBJDIR)/popen_.c:$(OBJDIR)/popen.h $(OBJDIR)/pqueue_.c:$(OBJDIR)/pqueue.h $(OBJDIR)/printf_.c:$(OBJDIR)/printf.h $(OBJDIR)/rebuild_.c:$(OBJDIR)/rebuild.h $(OBJDIR)/report_.c:$(OBJDIR)/report.h $(OBJDIR)/rss_.c:$(OBJDIR)/rss.h $(OBJDIR)/schema_.c:$(OBJDIR)/schema.h $(OBJDIR)/search_.c:$(OBJDIR)/search.h $(OBJDIR)/setup_.c:$(OBJDIR)/setup.h $(OBJDIR)/sha1_.c:$(OBJDIR)/sha1.h $(OBJDIR)/shun_.c:$(OBJDIR)/shun.h $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h $(OBJDIR)/style_.c:$(OBJDIR)/style.h $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h $(OBJDIR)/timeline_.c:$(OBJDIR)/timeline.h $(OBJDIR)/tkt_.c:$(OBJDIR)/tkt.h $(OBJDIR)/tktsetup_.c:$(OBJDIR)/tktsetup.h $(OBJDIR)/undo_.c:$(OBJDIR)/undo.h $(OBJDIR)/update_.c:$(OBJDIR)/update.h $(OBJDIR)/url_.c:$(OBJDIR)/url.h $(OBJDIR)/user_.c:$(OBJDIR)/user.h $(OBJDIR)/verify_.c:$(OBJDIR)/verify.h $(OBJDIR)/vfile_.c:$(OBJDIR)/vfile.h $(OBJDIR)/wiki_.c:$(OBJDIR)/wiki.h $(OBJDIR)/wikiformat_.c:$(OBJDIR)/wikiformat.h $(OBJDIR)/winhttp_.c:$(OBJDIR)/winhttp.h $(OBJDIR)/xfer_.c:$(OBJDIR)/xfer.h $(OBJDIR)/zip_.c:$(OBJDIR)/zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h $(OBJDIR)/VERSION.h
   388    391   	echo Done >$(OBJDIR)/headers
   389    392   
   390    393   $(OBJDIR)/headers: Makefile
   391    394   Makefile:
   392    395   $(OBJDIR)/add_.c:	$(SRCDIR)/add.c $(OBJDIR)/translate
   393    396   	$(TRANSLATE) $(SRCDIR)/add.c >$(OBJDIR)/add_.c
   394    397   
................................................................................
   700    703   $(OBJDIR)/name_.c:	$(SRCDIR)/name.c $(OBJDIR)/translate
   701    704   	$(TRANSLATE) $(SRCDIR)/name.c >$(OBJDIR)/name_.c
   702    705   
   703    706   $(OBJDIR)/name.o:	$(OBJDIR)/name_.c $(OBJDIR)/name.h  $(SRCDIR)/config.h
   704    707   	$(XTCC) -o $(OBJDIR)/name.o -c $(OBJDIR)/name_.c
   705    708   
   706    709   name.h:	$(OBJDIR)/headers
          710  +$(OBJDIR)/path_.c:	$(SRCDIR)/path.c $(OBJDIR)/translate
          711  +	$(TRANSLATE) $(SRCDIR)/path.c >$(OBJDIR)/path_.c
          712  +
          713  +$(OBJDIR)/path.o:	$(OBJDIR)/path_.c $(OBJDIR)/path.h  $(SRCDIR)/config.h
          714  +	$(XTCC) -o $(OBJDIR)/path.o -c $(OBJDIR)/path_.c
          715  +
          716  +path.h:	$(OBJDIR)/headers
   707    717   $(OBJDIR)/pivot_.c:	$(SRCDIR)/pivot.c $(OBJDIR)/translate
   708    718   	$(TRANSLATE) $(SRCDIR)/pivot.c >$(OBJDIR)/pivot_.c
   709    719   
   710    720   $(OBJDIR)/pivot.o:	$(OBJDIR)/pivot_.c $(OBJDIR)/pivot.h  $(SRCDIR)/config.h
   711    721   	$(XTCC) -o $(OBJDIR)/pivot.o -c $(OBJDIR)/pivot_.c
   712    722   
   713    723   pivot.h:	$(OBJDIR)/headers

Changes to win/Makefile.msc.

    36     36   BCC    = $(CC) $(CFLAGS)
    37     37   TCC    = $(CC) -c $(CFLAGS) $(MSCDEF) $(I18N) $(SSL) $(INCL)
    38     38   LIBS   = $(ZLIB) ws2_32.lib $(SSLLIB)
    39     39   LIBDIR = -LIBPATH:$(MSCDIR)\extra\lib -LIBPATH:$(ZLIBDIR)
    40     40   
    41     41   SQLITE_OPTIONS = /DSQLITE_OMIT_LOAD_EXTENSION=1 /DSQLITE_THREADSAFE=0 /DSQLITE_DEFAULT_FILE_FORMAT=4 /DSQLITE_ENABLE_STAT2 /Dlocaltime=fossil_localtime /DSQLITE_ENABLE_LOCKING_STYLE=0
    42     42   
    43         -SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c 
           43  +SRC   = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c leaf_.c login_.c main_.c manifest_.c md5_.c merge_.c merge3_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c rebuild_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c update_.c url_.c user_.c verify_.c vfile_.c wiki_.c wikiformat_.c winhttp_.c xfer_.c zip_.c 
    44     44   
    45         -OBJ   = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O 
           45  +OBJ   = $(OX)\add$O $(OX)\allrepo$O $(OX)\attach$O $(OX)\bag$O $(OX)\bisect$O $(OX)\blob$O $(OX)\branch$O $(OX)\browse$O $(OX)\captcha$O $(OX)\cgi$O $(OX)\checkin$O $(OX)\checkout$O $(OX)\clearsign$O $(OX)\clone$O $(OX)\comformat$O $(OX)\configure$O $(OX)\content$O $(OX)\db$O $(OX)\delta$O $(OX)\deltacmd$O $(OX)\descendants$O $(OX)\diff$O $(OX)\diffcmd$O $(OX)\doc$O $(OX)\encode$O $(OX)\event$O $(OX)\export$O $(OX)\file$O $(OX)\finfo$O $(OX)\graph$O $(OX)\gzip$O $(OX)\http$O $(OX)\http_socket$O $(OX)\http_ssl$O $(OX)\http_transport$O $(OX)\import$O $(OX)\info$O $(OX)\leaf$O $(OX)\login$O $(OX)\main$O $(OX)\manifest$O $(OX)\md5$O $(OX)\merge$O $(OX)\merge3$O $(OX)\name$O $(OX)\path$O $(OX)\pivot$O $(OX)\popen$O $(OX)\pqueue$O $(OX)\printf$O $(OX)\rebuild$O $(OX)\report$O $(OX)\rss$O $(OX)\schema$O $(OX)\search$O $(OX)\setup$O $(OX)\sha1$O $(OX)\shun$O $(OX)\skins$O $(OX)\sqlcmd$O $(OX)\stash$O $(OX)\stat$O $(OX)\style$O $(OX)\sync$O $(OX)\tag$O $(OX)\tar$O $(OX)\th_main$O $(OX)\timeline$O $(OX)\tkt$O $(OX)\tktsetup$O $(OX)\undo$O $(OX)\update$O $(OX)\url$O $(OX)\user$O $(OX)\verify$O $(OX)\vfile$O $(OX)\wiki$O $(OX)\wikiformat$O $(OX)\winhttp$O $(OX)\xfer$O $(OX)\zip$O $(OX)\shell$O $(OX)\sqlite3$O $(OX)\th$O $(OX)\th_lang$O 
    46     46   
    47     47   
    48     48   APPNAME = $(OX)\fossil$(E)
    49     49   
    50     50   all: $(OX) $(APPNAME)
    51     51   
    52     52   $(APPNAME) : translate$E mkindex$E headers $(OBJ) $(OX)\linkopts
    53     53   	cd $(OX) 
    54     54   	link -LINK -OUT:$@ $(LIBDIR) @linkopts
    55     55   
    56     56   $(OX)\linkopts: $B\win\Makefile.msc
    57         -	echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
           57  +	echo add allrepo attach bag bisect blob branch browse captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo graph gzip http http_socket http_ssl http_transport import info leaf login main manifest md5 merge merge3 name path pivot popen pqueue printf rebuild report rss schema search setup sha1 shun skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo update url user verify vfile wiki wikiformat winhttp xfer zip sqlite3 th th_lang > $@
    58     58   	echo $(LIBS) >> $@
    59     59   
    60     60   
    61     61   
    62     62   
    63     63   $(OX):
    64     64   	@-mkdir $@
................................................................................
   367    367   	translate$E $** > $@
   368    368   
   369    369   $(OX)\name$O : name_.c name.h
   370    370   	$(TCC) /Fo$@ -c name_.c
   371    371   
   372    372   name_.c : $(SRCDIR)\name.c
   373    373   	translate$E $** > $@
          374  +
          375  +$(OX)\path$O : path_.c path.h
          376  +	$(TCC) /Fo$@ -c path_.c
          377  +
          378  +path_.c : $(SRCDIR)\path.c
          379  +	translate$E $** > $@
   374    380   
   375    381   $(OX)\pivot$O : pivot_.c pivot.h
   376    382   	$(TCC) /Fo$@ -c pivot_.c
   377    383   
   378    384   pivot_.c : $(SRCDIR)\pivot.c
   379    385   	translate$E $** > $@
   380    386   
................................................................................
   579    585   $(OX)\zip$O : zip_.c zip.h
   580    586   	$(TCC) /Fo$@ -c zip_.c
   581    587   
   582    588   zip_.c : $(SRCDIR)\zip.c
   583    589   	translate$E $** > $@
   584    590   
   585    591   headers: makeheaders$E page_index.h VERSION.h
   586         -	makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
          592  +	makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h leaf_.c:leaf.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h
   587    593   	@copy /Y nul: headers