Fossil

Check-in [b9abb86798]
Login

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

Overview
Comment:Infrastructure changes toward adding graphical merging options.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b9abb86798611bd490b32acd19632aeb314d3a76
User & Date: drh 2011-02-21 14:21:57.889
Context
2011-02-21
16:33
Add the ability to use a graphical merging tool to resolve merge conflicts. Even without a configured graphical tool, leave files behind (VCS droppings) that contain the baseline, original, and merged files. check-in: 9b7a6f80b2 user: drh tags: trunk
14:21
Infrastructure changes toward adding graphical merging options. check-in: b9abb86798 user: drh tags: trunk
13:17
Do not assume that the PATH_INFO environment variable is set by CGI. Give it a default value to avoid segfaults (on Solaris). check-in: 88383d8d4a user: drh tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/merge.c.
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
    int idv = db_column_int(&q, 1);
    int ridp = db_column_int(&q, 2);
    int ridv = db_column_int(&q, 3);
    int isBinary = db_column_int(&q, 4);
    const char *zName = db_column_text(&q, 5);
    int rc;
    char *zFullPath;
    Blob m, p, v, r;
    /* Do a 3-way merge of idp->idm into idp->idv.  The results go into idv. */
    if( detailFlag ){
      printf("MERGE %s  (pivot=%d v1=%d v2=%d)\n", zName, ridp, ridm, ridv);
    }else{
      printf("MERGE %s\n", zName);
    }
    undo_save(zName);
    zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
    content_get(ridp, &p);
    content_get(ridm, &m);
    blob_zero(&v);
    blob_read_from_file(&v, zFullPath);
    if( isBinary ){
      rc = -1;
      blob_zero(&r);
    }else{
      rc = blob_merge(&p, &v, &m, &r);
    }
    if( rc>=0 ){
      if( !nochangeFlag ){
        blob_write_to_file(&r, zFullPath);
      }
      db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
      if( rc>0 ){
        printf("***** %d merge conflicts in %s\n", rc, zName);
        nConflict++;
      }
    }else{
      printf("***** Cannot merge binary file %s\n", zName);
      nConflict++;
    }
    blob_reset(&p);
    blob_reset(&m);
    blob_reset(&v);
    blob_reset(&r);
    db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(%d,%d)",
                  idv,ridm);
  }
  db_finalize(&q);

  /*







|










<
<




|
















<







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361


362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

383
384
385
386
387
388
389
    int idv = db_column_int(&q, 1);
    int ridp = db_column_int(&q, 2);
    int ridv = db_column_int(&q, 3);
    int isBinary = db_column_int(&q, 4);
    const char *zName = db_column_text(&q, 5);
    int rc;
    char *zFullPath;
    Blob m, p, r;
    /* Do a 3-way merge of idp->idm into idp->idv.  The results go into idv. */
    if( detailFlag ){
      printf("MERGE %s  (pivot=%d v1=%d v2=%d)\n", zName, ridp, ridm, ridv);
    }else{
      printf("MERGE %s\n", zName);
    }
    undo_save(zName);
    zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
    content_get(ridp, &p);
    content_get(ridm, &m);


    if( isBinary ){
      rc = -1;
      blob_zero(&r);
    }else{
      rc = merge_3way(&p, zFullPath, &m, &r);
    }
    if( rc>=0 ){
      if( !nochangeFlag ){
        blob_write_to_file(&r, zFullPath);
      }
      db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
      if( rc>0 ){
        printf("***** %d merge conflicts in %s\n", rc, zName);
        nConflict++;
      }
    }else{
      printf("***** Cannot merge binary file %s\n", zName);
      nConflict++;
    }
    blob_reset(&p);
    blob_reset(&m);

    blob_reset(&r);
    db_multi_exec("INSERT OR IGNORE INTO vmerge(id,merge) VALUES(%d,%d)",
                  idv,ridm);
  }
  db_finalize(&q);

  /*
Changes to src/merge3.c.
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
** to pV2.
**
** The return is 0 upon complete success. If any input file is binary,
** -1 is returned and pOut is unmodified.  If there are merge
** conflicts, the merge proceeds as best as it can and the number 
** of conflicts is returns
*/
int blob_merge(Blob *pPivot, Blob *pV1, Blob *pV2, Blob *pOut){
  int *aC1;              /* Changes from pPivot to pV1 */
  int *aC2;              /* Changes from pPivot to pV2 */
  int i1, i2;            /* Index into aC1[] and aC2[] */
  int nCpy, nDel, nIns;  /* Number of lines to copy, delete, or insert */
  int limit1, limit2;    /* Sizes of aC1[] and aC2[] */
  int nConflict = 0;     /* Number of merge conflicts seen so far */
  static const char zBegin[] =







|







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
** to pV2.
**
** The return is 0 upon complete success. If any input file is binary,
** -1 is returned and pOut is unmodified.  If there are merge
** conflicts, the merge proceeds as best as it can and the number 
** of conflicts is returns
*/
static int blob_merge(Blob *pPivot, Blob *pV1, Blob *pV2, Blob *pOut){
  int *aC1;              /* Changes from pPivot to pV1 */
  int *aC2;              /* Changes from pPivot to pV2 */
  int i1, i2;            /* Index into aC1[] and aC2[] */
  int nCpy, nDel, nIns;  /* Number of lines to copy, delete, or insert */
  int limit1, limit2;    /* Sizes of aC1[] and aC2[] */
  int nConflict = 0;     /* Number of merge conflicts seen so far */
  static const char zBegin[] =
327
328
329
330
331
332
333






























    fossil_exit(1);
  }
  blob_reset(&pivot);
  blob_reset(&v1);
  blob_reset(&v2);
  blob_reset(&merged);
}





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
327
328
329
330
331
332
333
334
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
    fossil_exit(1);
  }
  blob_reset(&pivot);
  blob_reset(&v1);
  blob_reset(&v2);
  blob_reset(&merged);
}

/*
** This routine is a wrapper around blob_merge() with enhancements:
**
**    (1) If the merge-command is defined, then use the external merging
**        program specified instead of the built-in blob-merge to do the
**        merging.  Panic if the external merger fails.
**
**    (2) If gmerge-command is defined and there are merge conflicts in
**        blob_merge() then invoke the external graphical merger to resolve
**        the conflicts.
**
** Otherwise, the interface and actions are the same as for blob_merge().
**
** The enhancements are planned - they are not yet implemented.
*/
int merge_3way(
  Blob *pPivot,       /* Common ancestor (older) */
  const char *zV1,    /* Name of file for version merging into (mine) */
  Blob *pV2,          /* Version merging from (yours) */
  Blob *pOut          /* Output written here */
){
  Blob v1;            /* Content of zV1 */
  int rc;             /* Return code of subroutines and this routine */

  blob_read_from_file(&v1, zV1);
  rc = blob_merge(pPivot, &v1, pV2, pOut);
  blob_reset(&v1);
  return rc;
}
Changes to src/stash.c.
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
      blob_read_from_file(&disk, zOPath);     
      content_get(rid, &a);
      blob_delta_apply(&a, &delta, &b);
      if( blob_compare(&disk, &a)==0 ){
        blob_write_to_file(&b, zNPath);
        printf("UPDATE %s\n", zNew);
      }else{
        int rc = blob_merge(&a, &disk, &b, &out);
        blob_write_to_file(&out, zNPath);
        if( rc ){
          printf("CONFLICT %s\n", zNew);
          nConflict++;
        }else{
          printf("MERGE %s\n", zNew);
        }







|







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
      blob_read_from_file(&disk, zOPath);     
      content_get(rid, &a);
      blob_delta_apply(&a, &delta, &b);
      if( blob_compare(&disk, &a)==0 ){
        blob_write_to_file(&b, zNPath);
        printf("UPDATE %s\n", zNew);
      }else{
        int rc = merge_3way(&a, zOPath, &b, &out);
        blob_write_to_file(&out, zNPath);
        if( rc ){
          printf("CONFLICT %s\n", zNew);
          nConflict++;
        }else{
          printf("MERGE %s\n", zNew);
        }
Changes to src/update.c.
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
      }else{
        printf("REMOVE %s\n", zName);
        undo_save(zName);
        if( !nochangeFlag ) unlink(zFullPath);
      }
    }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
      /* Merge the changes in the current tree into the target version */
      Blob e, r, t, v;
      int rc;
      if( nameChng ){
        printf("MERGE %s -> %s\n", zName, zNewName);
      }else{
        printf("MERGE %s\n", zName);
      }
      undo_save(zName);
      content_get(ridt, &t);
      content_get(ridv, &v);
      blob_zero(&e);
      blob_read_from_file(&e, zFullPath);
      rc = blob_merge(&v, &e, &t, &r);
      if( rc>=0 ){
        if( !nochangeFlag ) blob_write_to_file(&r, zFullNewPath);
        if( rc>0 ){
          printf("***** %d merge conflicts in %s\n", rc, zNewName);
          nConflict++;
        }
      }else{
        if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath);
        printf("***** Cannot merge binary file %s\n", zNewName);
        nConflict++;
      }
      if( nameChng && !nochangeFlag ) unlink(zFullPath);
      blob_reset(&v);
      blob_reset(&e);
      blob_reset(&t);
      blob_reset(&r);
    }else{
      if( chnged ){
        if( verboseFlag ) printf("EDITED %s\n", zName);
      }else{
        db_bind_int(&mtimeXfer, ":idv", idv);







|









<
|
<













<







360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376

377

378
379
380
381
382
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
      }else{
        printf("REMOVE %s\n", zName);
        undo_save(zName);
        if( !nochangeFlag ) unlink(zFullPath);
      }
    }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){
      /* Merge the changes in the current tree into the target version */
      Blob r, t, v;
      int rc;
      if( nameChng ){
        printf("MERGE %s -> %s\n", zName, zNewName);
      }else{
        printf("MERGE %s\n", zName);
      }
      undo_save(zName);
      content_get(ridt, &t);
      content_get(ridv, &v);

      rc = merge_3way(&v, zFullPath, &t, &r);

      if( rc>=0 ){
        if( !nochangeFlag ) blob_write_to_file(&r, zFullNewPath);
        if( rc>0 ){
          printf("***** %d merge conflicts in %s\n", rc, zNewName);
          nConflict++;
        }
      }else{
        if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath);
        printf("***** Cannot merge binary file %s\n", zNewName);
        nConflict++;
      }
      if( nameChng && !nochangeFlag ) unlink(zFullPath);
      blob_reset(&v);

      blob_reset(&t);
      blob_reset(&r);
    }else{
      if( chnged ){
        if( verboseFlag ) printf("EDITED %s\n", zName);
      }else{
        db_bind_int(&mtimeXfer, ":idv", idv);