Fossil

Check-in [21acce3c]
Login

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

Overview
Comment:Add additional trace output with the --debug option on "fossil merge" and especially on filename change tracking.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 21acce3c350f582ff9bde95b0784d6be4c641780
User & Date: drh 2011-09-02 13:51:16
Context
2011-09-02
13:54
Fix a missing \n on the trace output of the previous check-in. Also fix a redundancy in the computation of symbolic links. check-in: 59717678 user: drh tags: trunk
13:51
Add additional trace output with the --debug option on "fossil merge" and especially on filename change tracking. check-in: 21acce3c user: drh tags: trunk
12:39
Merge symlink fixes into trunk. check-in: c97535c5 user: dmitry tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/merge.c.

146
147
148
149
150
151
152









153
154
155
156
157
158
159
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
...
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
248
249
250
251
252
253
254
255




256
257
258
259
260
261
262
263
    fossil_fatal("not a version: record #%d", pid);
  }
  vfile_check_signature(vid, 1, 0);
  db_begin_transaction();
  if( !nochangeFlag ) undo_begin();
  load_vfile_from_rid(mid);
  load_vfile_from_rid(pid);










  /*
  ** The vfile.pathname field is used to match files against each other.  The
  ** FV table contains one row for each each unique filename in
  ** in the current checkout, the pivot, and the version being merged.
  */
  db_multi_exec(
................................................................................
    " FROM vfile WHERE vid=%d",
    vid
  );

  /*
  ** Compute name changes from P->V
  */
  find_filename_changes(vid, pid, &nChng, &aChng);
  if( nChng ){
    for(i=0; i<nChng; i++){
      char *z;
      z = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
      db_multi_exec(
        "UPDATE fv SET fnp=%Q, fnm=%Q"
        " WHERE fn=(SELECT name FROM filename WHERE fnid=%d)",
................................................................................
    "  WHERE vid=%d AND pathname NOT IN (SELECT fnp FROM fv)",
    pid
  );

  /*
  ** Compute name changes from P->M
  */
  find_filename_changes(pid, mid, &nChng, &aChng);
  if( nChng ){
    if( nChng>4 ) db_multi_exec("CREATE INDEX fv_fnp ON fv(fnp)");
    for(i=0; i<nChng; i++){
      db_multi_exec(
        "UPDATE fv SET fnm=(SELECT name FROM filename WHERE fnid=%d)"
        " WHERE fnp=(SELECT name FROM filename WHERE fnid=%d)",
        aChng[i*2+1], aChng[i*2]
................................................................................
  ** Compute the file version ids for P and M.
  */
  db_multi_exec(
    "UPDATE fv SET"
    " idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnp),0),"
    " ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnp),0),"
    " idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnm),0),"
    " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0)",




    pid, pid, mid, mid
  );

  /*
  **  Add islink information for files in V and M
  **
  */
  db_multi_exec(







>
>
>
>
>
>
>
>
>







 







|







 







|







 







|
>
>
>
>
|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
...
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
    fossil_fatal("not a version: record #%d", pid);
  }
  vfile_check_signature(vid, 1, 0);
  db_begin_transaction();
  if( !nochangeFlag ) undo_begin();
  load_vfile_from_rid(mid);
  load_vfile_from_rid(pid);
  if( debugFlag ){
    char *z;
    z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pid);
    fossil_print("P=%d %z\n", pid, z);
    z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
    fossil_print("M=%d %z\n", mid, z);
    z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
    fossil_print("V=%d %z\n", vid, z);
  }

  /*
  ** The vfile.pathname field is used to match files against each other.  The
  ** FV table contains one row for each each unique filename in
  ** in the current checkout, the pivot, and the version being merged.
  */
  db_multi_exec(
................................................................................
    " FROM vfile WHERE vid=%d",
    vid
  );

  /*
  ** Compute name changes from P->V
  */
  find_filename_changes(vid, pid, &nChng, &aChng, debugFlag ? "P->V" : 0);
  if( nChng ){
    for(i=0; i<nChng; i++){
      char *z;
      z = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
      db_multi_exec(
        "UPDATE fv SET fnp=%Q, fnm=%Q"
        " WHERE fn=(SELECT name FROM filename WHERE fnid=%d)",
................................................................................
    "  WHERE vid=%d AND pathname NOT IN (SELECT fnp FROM fv)",
    pid
  );

  /*
  ** Compute name changes from P->M
  */
  find_filename_changes(pid, mid, &nChng, &aChng, debugFlag ? "P->M" : 0);
  if( nChng ){
    if( nChng>4 ) db_multi_exec("CREATE INDEX fv_fnp ON fv(fnp)");
    for(i=0; i<nChng; i++){
      db_multi_exec(
        "UPDATE fv SET fnm=(SELECT name FROM filename WHERE fnid=%d)"
        " WHERE fnp=(SELECT name FROM filename WHERE fnid=%d)",
        aChng[i*2+1], aChng[i*2]
................................................................................
  ** Compute the file version ids for P and M.
  */
  db_multi_exec(
    "UPDATE fv SET"
    " idp=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnp),0),"
    " ridp=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnp),0),"
    " idm=coalesce((SELECT id FROM vfile WHERE vid=%d AND pathname=fnm),0),"
    " ridm=coalesce((SELECT rid FROM vfile WHERE vid=%d AND pathname=fnm),0),"
    " islinkv=coalesce((SELECT islink FROM vfile"
                    " WHERE vid=%d AND pathname=fnm),0),"
    " islinkm=coalesce((SELECT islink FROM vfile"
                    " WHERE vid=%d AND pathname=fnm),0)",
    pid, pid, mid, mid, vid, mid
  );

  /*
  **  Add islink information for files in V and M
  **
  */
  db_multi_exec(

Changes to src/path.c.

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
...
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
...
338
339
340
341
342
343
344
345


346
347
348
349
350
351
352
353
354
355
356
357

358
359
360
361
362
363
364
365
366
...
385
386
387
388
389
390
391









392
393
394
395
396
397
398
...
411
412
413
414
415
416
417








418
419
420
421
422
423
424
...
435
436
437
438
439
440
441
442

443
444
445


446
447
448
449
450
451
452
453
454
455


456

  PathNode *p;
  while( path.pAll ){
    p = path.pAll;
    path.pAll = p->pAll;
    fossil_free(p);
  }
  bag_clear(&path.seen);
  path.pCurrent = 0;
  path.pAll = 0;
  path.pEnd = 0;
  path.nStep = 0;
}

/*
** Construct the path from path.pStart to path.pEnd in the u.pTo fields.
*/
void path_reverse_path(void){
  PathNode *p;
................................................................................
  for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
    char *z;
    z = db_text(0,
      "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
      "  FROM blob, event"
      " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
      p->rid, p->rid);
    fossil_print("%4d: %s", n, z);
    fossil_free(z);
    if( p->u.pTo ){
      fossil_print(" is a %s of\n", 
                   p->u.pTo->fromIsParent ? "parent" : "child");
    }else{
      fossil_print("\n");
    }
................................................................................
  for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
    char *z;
    z = db_text(0,
      "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
      "  FROM blob, event"
      " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
      p->rid, p->rid);
    fossil_print("%4d: %s", n, z);
    fossil_free(z);
    if( p->rid==iFrom ) fossil_print(" VERSION1");
    if( p->rid==iTo ) fossil_print(" VERSION2");
    if( p->rid==iPivot ) fossil_print(" PIVOT");
    fossil_print("\n");
  }
}
................................................................................

/*
** Compute all file name changes that occur going from checkin iFrom
** to checkin iTo.
**
** The number of name changes is written into *pnChng.  For each name
** change, two integers are allocated for *piChng.  The first is the 
** filename.fnid for the original name and the second is for new name.


** Space to hold *piChng is obtained from fossil_malloc() and should
** be released by the caller.
**
** This routine really has nothing to do with pathion.  It is located
** in this path.c module in order to leverage some of the path
** infrastructure.
*/
void find_filename_changes(
  int iFrom,
  int iTo,
  int *pnChng,
  int **aiChng

){
  PathNode *p;           /* For looping over path from iFrom to iTo */
  NameChange *pAll = 0;    /* List of all name changes seen so far */
  NameChange *pChng;       /* For looping through the name change list */
  int nChng = 0;           /* Number of files whose names have changed */
  int *aChng;              /* Two integers per name change */
  int i;                   /* Loop counter */
  Stmt q1;                 /* Query of name changes */

................................................................................
      if( p->fromIsParent ){
        fnid = db_column_int(&q1, 1);
        pfnid = db_column_int(&q1, 0);
      }else{
        fnid = db_column_int(&q1, 0);
        pfnid = db_column_int(&q1, 1);
      }









      for(pChng=pAll; pChng; pChng=pChng->pNext){
        if( pChng->curName==pfnid ){
          pChng->newName = fnid;
          break;
        }
      }
      if( pChng==0 ){
................................................................................
  db_finalize(&q1);
  if( nChng ){
    *pnChng = nChng;
    aChng = *aiChng = fossil_malloc( nChng*2*sizeof(int) );
    for(pChng=pAll, i=0; pChng; pChng=pChng->pNext, i+=2){
      aChng[i] = pChng->origName;
      aChng[i+1] = pChng->newName;








    }
    while( pAll ){
      pChng = pAll;
      pAll = pAll->pNext;
      fossil_free(pChng);
    }
  }
................................................................................
  int iFrom;
  int iTo;
  int *aChng;
  int nChng;
  int i;

  db_find_and_open_repository(0,0);
  if( g.argc!=4 ) usage("VERSION1 VERSION2");

  iFrom = name_to_rid(g.argv[2]);
  iTo = name_to_rid(g.argv[3]);
  find_filename_changes(iFrom, iTo, &nChng, &aChng);


  for(i=0; i<nChng; i++){
    char *zFrom, *zTo;

    zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
    zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
    fossil_print("[%s] -> [%s]\n", zFrom, zTo);
    fossil_free(zFrom);
    fossil_free(zTo);
  }
  fossil_free(aChng);


}








|
<
<
<







 







|







 







|







 







|
>
>



|




|
|
|
|
>

|







 







>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>







 







|
>
|
|
|
>
>
|
|

|
|
|
|
|
|
|
>
>
|
>
87
88
89
90
91
92
93
94



95
96
97
98
99
100
101
...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
...
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
...
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
  PathNode *p;
  while( path.pAll ){
    p = path.pAll;
    path.pAll = p->pAll;
    fossil_free(p);
  }
  bag_clear(&path.seen);
  memset(&path, 0, sizeof(&path));



}

/*
** Construct the path from path.pStart to path.pEnd in the u.pTo fields.
*/
void path_reverse_path(void){
  PathNode *p;
................................................................................
  for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
    char *z;
    z = db_text(0,
      "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
      "  FROM blob, event"
      " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
      p->rid, p->rid);
    fossil_print("%4d: %5d %s", n, p->rid, z);
    fossil_free(z);
    if( p->u.pTo ){
      fossil_print(" is a %s of\n", 
                   p->u.pTo->fromIsParent ? "parent" : "child");
    }else{
      fossil_print("\n");
    }
................................................................................
  for(n=1, p=path.pStart; p; p=p->u.pTo, n++){
    char *z;
    z = db_text(0,
      "SELECT substr(uuid,1,12) || ' ' || datetime(mtime)"
      "  FROM blob, event"
      " WHERE blob.rid=%d AND event.objid=%d AND event.type='ci'",
      p->rid, p->rid);
    fossil_print("%4d: %5d %s", n, p->rid, z);
    fossil_free(z);
    if( p->rid==iFrom ) fossil_print(" VERSION1");
    if( p->rid==iTo ) fossil_print(" VERSION2");
    if( p->rid==iPivot ) fossil_print(" PIVOT");
    fossil_print("\n");
  }
}
................................................................................

/*
** Compute all file name changes that occur going from checkin iFrom
** to checkin iTo.
**
** The number of name changes is written into *pnChng.  For each name
** change, two integers are allocated for *piChng.  The first is the 
** filename.fnid for the original name as seen in check-in iFrom and
** the second is for new name as it is used in check-in iTo.
**
** Space to hold *piChng is obtained from fossil_malloc() and should
** be released by the caller.
**
** This routine really has nothing to do with path.  It is located
** in this path.c module in order to leverage some of the path
** infrastructure.
*/
void find_filename_changes(
  int iFrom,               /* Ancestor check-in */
  int iTo,                 /* Recent check-in */
  int *pnChng,             /* Number of name changes along the path */
  int **aiChng,            /* Name changes */
  const char *zDebug       /* Generate trace output if no NULL */
){
  PathNode *p;             /* For looping over path from iFrom to iTo */
  NameChange *pAll = 0;    /* List of all name changes seen so far */
  NameChange *pChng;       /* For looping through the name change list */
  int nChng = 0;           /* Number of files whose names have changed */
  int *aChng;              /* Two integers per name change */
  int i;                   /* Loop counter */
  Stmt q1;                 /* Query of name changes */

................................................................................
      if( p->fromIsParent ){
        fnid = db_column_int(&q1, 1);
        pfnid = db_column_int(&q1, 0);
      }else{
        fnid = db_column_int(&q1, 0);
        pfnid = db_column_int(&q1, 1);
      }
      if( zDebug ){
        fossil_print("%s at %d %.10z: %d[%z] -> %d[%z]\n",
           zDebug, p->rid, 
           db_text(0, "SELECT uuid FROM blob WHERE rid=%d", p->rid),
           pfnid,
           db_text(0, "SELECT name FROM filename WHERE fnid=%d", pfnid),
           fnid,
           db_text(0, "SELECT name FROM filename WHERE fnid=%d", fnid));
      }
      for(pChng=pAll; pChng; pChng=pChng->pNext){
        if( pChng->curName==pfnid ){
          pChng->newName = fnid;
          break;
        }
      }
      if( pChng==0 ){
................................................................................
  db_finalize(&q1);
  if( nChng ){
    *pnChng = nChng;
    aChng = *aiChng = fossil_malloc( nChng*2*sizeof(int) );
    for(pChng=pAll, i=0; pChng; pChng=pChng->pNext, i+=2){
      aChng[i] = pChng->origName;
      aChng[i+1] = pChng->newName;
      if( zDebug ){
        fossil_print("%s summary %d[%z] -> %d[%z]\n",
           zDebug,
           aChng[i],
           db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i]),
           aChng[i+1],
           db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i+1]));
      }
    }
    while( pAll ){
      pChng = pAll;
      pAll = pAll->pNext;
      fossil_free(pChng);
    }
  }
................................................................................
  int iFrom;
  int iTo;
  int *aChng;
  int nChng;
  int i;

  db_find_and_open_repository(0,0);
  if( g.argc<4 ) usage("VERSION1 VERSION2");
  while( g.argc>=4 ){
    iFrom = name_to_rid(g.argv[2]);
    iTo = name_to_rid(g.argv[3]);
    find_filename_changes(iFrom, iTo, &nChng, &aChng, 0);
    fossil_print("------ Changes for (%d) %s -> (%d) %s\n",
                 iFrom, g.argv[2], iTo, g.argv[3]);
    for(i=0; i<nChng; i++){
      char *zFrom, *zTo;

      zFrom = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2]);
      zTo = db_text(0, "SELECT name FROM filename WHERE fnid=%d", aChng[i*2+1]);
      fossil_print("[%s] -> [%s]\n", zFrom, zTo);
      fossil_free(zFrom);
      fossil_free(zTo);
    }
    fossil_free(aChng);
    g.argv += 2;
    g.argc -= 2;
  }
}

Changes to src/update.c.

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
    "   FROM vfile WHERE vid=%d",
    vid
  );

  /* Compute file name changes on V->T.  Record name changes in files that
  ** have changed locally.
  */
  find_filename_changes(vid, tid, &nChng, &aChng);
  if( nChng ){
    for(i=0; i<nChng; i++){
      db_multi_exec(
        "UPDATE fv"
        "   SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
        " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
        aChng[i*2+1], aChng[i*2]







|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
    "   FROM vfile WHERE vid=%d",
    vid
  );

  /* Compute file name changes on V->T.  Record name changes in files that
  ** have changed locally.
  */
  find_filename_changes(vid, tid, &nChng, &aChng, debugFlag ? "V->T": 0);
  if( nChng ){
    for(i=0; i<nChng; i++){
      db_multi_exec(
        "UPDATE fv"
        "   SET fnt=(SELECT name FROM filename WHERE fnid=%d)"
        " WHERE fn=(SELECT name FROM filename WHERE fnid=%d) AND chnged",
        aChng[i*2+1], aChng[i*2]