Login
Changes On Branch no-common-ancestor
Login

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

Changes In Branch no-common-ancestor Excluding Merge-Ins

This is equivalent to a diff from 0fe561416a to 3ca3706652

2023-04-26
16:24
Merge no-common-ancestor branch into trunk. check-in: 0657571903 user: stephan tags: trunk
16:23
Remove the no-common-ancestor check from the merge algorith, for conformance with fossil(1)'s new behavior. Closed-Leaf check-in: 3ca3706652 user: stephan tags: no-common-ancestor
2023-04-23
12:09
Patch some interrupted-mid-sentence comments. check-in: 1bb1139c7b user: stephan tags: no-common-ancestor
12:07
Apply upstream [fossil:7c75e47b3c130ff1]: when merging files with no common ancestor, treat it as if an imaginary common ancestor were an empty file. We currently retain the no-common-ancestor diagnosis but may yet remove it or augment it to permit the user to specify which side of the merge to retain. check-in: 30bd3e8b14 user: stephan tags: no-common-ancestor
2023-04-21
15:57
Remove sqlite3ext.h and a C-side reference to it. check-in: 0fe561416a user: stephan tags: trunk
2023-04-19
12:46
Update to latest upstream sqlite3ext.h (used by ext_regexp.c). check-in: 231fed9533 user: stephan tags: trunk

Changes to f-apps/f-merge.c.
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
    case FSL_MERGE_FCHANGE_COPIED: rc="c"; break;
    case FSL_MERGE_FCHANGE_RM: rc="-"; break;
    case FSL_MERGE_FCHANGE_MERGED: rc="m"; break;
    case FSL_MERGE_FCHANGE_CONFLICT_MERGED: rc="!m"; break;
    case FSL_MERGE_FCHANGE_CONFLICT_ADDED_UNMANAGED: rc="!+"; break;
    case FSL_MERGE_FCHANGE_CONFLICT_SYMLINK: rc="!s"; break;
    case FSL_MERGE_FCHANGE_CONFLICT_BINARY: rc="!b"; break;
    case FSL_MERGE_FCHANGE_CONFLICT_ANCESTOR: rc="!a"; break;
    case FSL_MERGE_FCHANGE_RENAMED: rc="r"; break;
    case FSL_MERGE_FCHANGE_count:
    case FSL_MERGE_FCHANGE_NONE: rc="!!!";
      fsl__fatal(FSL_RC_NYI,"Cannot happen: FSL_MERGE_FCHANGE_NONE");
      break;
  }
  return rc;







<







52
53
54
55
56
57
58

59
60
61
62
63
64
65
    case FSL_MERGE_FCHANGE_COPIED: rc="c"; break;
    case FSL_MERGE_FCHANGE_RM: rc="-"; break;
    case FSL_MERGE_FCHANGE_MERGED: rc="m"; break;
    case FSL_MERGE_FCHANGE_CONFLICT_MERGED: rc="!m"; break;
    case FSL_MERGE_FCHANGE_CONFLICT_ADDED_UNMANAGED: rc="!+"; break;
    case FSL_MERGE_FCHANGE_CONFLICT_SYMLINK: rc="!s"; break;
    case FSL_MERGE_FCHANGE_CONFLICT_BINARY: rc="!b"; break;

    case FSL_MERGE_FCHANGE_RENAMED: rc="r"; break;
    case FSL_MERGE_FCHANGE_count:
    case FSL_MERGE_FCHANGE_NONE: rc="!!!";
      fsl__fatal(FSL_RC_NYI,"Cannot happen: FSL_MERGE_FCHANGE_NONE");
      break;
  }
  return rc;
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
       "Added, overwriting an unmanaged file"},
      {FSL_MERGE_FCHANGE_CONFLICT_MERGED, 0,
       "Merged with conflicts"},
      {FSL_MERGE_FCHANGE_CONFLICT_SYMLINK, 0,
       "Symlink cannot be merged"},
      {FSL_MERGE_FCHANGE_CONFLICT_BINARY, 0,
       "Binary content cannot be merged"},
      {FSL_MERGE_FCHANGE_CONFLICT_ANCESTOR, 0,
       "No common ancestor found. "
       "Normally means a new file was merged in"},
      {FSL_MERGE_FCHANGE_NONE,NULL,NULL}
    };
    f_out("\nLEGEND:\n");
    for(struct legend * l = &leg[0]; l->desc; ++l){
      if(App.mCounts[l->fct]){
        f_out("   %-3s    %s\n",
              l->altSym ? l->altSym : fsl__merge_fchange_label(l->fct),







<
<
<







213
214
215
216
217
218
219



220
221
222
223
224
225
226
       "Added, overwriting an unmanaged file"},
      {FSL_MERGE_FCHANGE_CONFLICT_MERGED, 0,
       "Merged with conflicts"},
      {FSL_MERGE_FCHANGE_CONFLICT_SYMLINK, 0,
       "Symlink cannot be merged"},
      {FSL_MERGE_FCHANGE_CONFLICT_BINARY, 0,
       "Binary content cannot be merged"},



      {FSL_MERGE_FCHANGE_NONE,NULL,NULL}
    };
    f_out("\nLEGEND:\n");
    for(struct legend * l = &leg[0]; l->desc; ++l){
      if(App.mCounts[l->fct]){
        f_out("   %-3s    %s\n",
              l->altSym ? l->altSym : fsl__merge_fchange_label(l->fct),
Changes to include/fossil-scm/checkout.h.
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
   was skipped over for merge purposes.

   fossil(1) simply skips over, with a warning, binaries during a
   merge, so we do the same (for lack of a better option).
*/
FSL_MERGE_FCHANGE_CONFLICT_BINARY,
/**
   Indicates that the given file cannot be merged because no common
   ancestor can be found for it. This condition is not strictly fatal
   but does indicate a problem with the input data. Merging will
   continue unless the fsl_merge_f() to which this is reported returns
   non-0 to cancel it.  This particular status is reported very early
   in the fsl_ckout_merge() process, before any files have been
   written by the merge, thus the callback can effectively abort the
   merge without side-effects by returning non-0 if this status is
   reported to it. If the fsl_ckout_merge() call has no callback set,
   this case will go silently undiagnosed!

   Potential TODO: add a flag to fsl_merge_opt to tell it to treat any
   of these cases as merge-fatal.
*/
FSL_MERGE_FCHANGE_CONFLICT_ANCESTOR,
/**
   File was renamed in the updated-to version. If a file is both
   modified and renamed, it will be reported twice: once for each type
   of change. The new name is reported via fsl_merge_state::filename
   and the previous name via fsl_merge_state::priorName.
*/
FSL_MERGE_FCHANGE_RENAMED,
/**







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







2589
2590
2591
2592
2593
2594
2595
















2596
2597
2598
2599
2600
2601
2602
   was skipped over for merge purposes.

   fossil(1) simply skips over, with a warning, binaries during a
   merge, so we do the same (for lack of a better option).
*/
FSL_MERGE_FCHANGE_CONFLICT_BINARY,
/**
















   File was renamed in the updated-to version. If a file is both
   modified and renamed, it will be reported twice: once for each type
   of change. The new name is reported via fsl_merge_state::filename
   and the previous name via fsl_merge_state::priorName.
*/
FSL_MERGE_FCHANGE_RENAMED,
/**
Changes to src/merge.c.
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    rc = fsl_cx_exec(f,
      "INSERT INTO " FSL__TABLE_PIVOT "(rid, mtime, pending, src)"
      "  SELECT %" FSL_ID_T_PFMT ", mtime, 1, 1 "
      "  FROM event WHERE objid=%" FSL_ID_T_PFMT
      " AND type='ci' LIMIT 1",
      rid, rid );
  }
  return rc;  
}

/**
   Set a secondary file of a merge. The primary file must be set
   first. There must be at least one secondary but there can be more
   than one if desired.








|







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    rc = fsl_cx_exec(f,
      "INSERT INTO " FSL__TABLE_PIVOT "(rid, mtime, pending, src)"
      "  SELECT %" FSL_ID_T_PFMT ", mtime, 1, 1 "
      "  FROM event WHERE objid=%" FSL_ID_T_PFMT
      " AND type='ci' LIMIT 1",
      rid, rid );
  }
  return rc;
}

/**
   Set a secondary file of a merge. The primary file must be set
   first. There must be at least one secondary but there can be more
   than one if desired.

810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
  rc = opt->callback(&mState); \
  mState.priorName = NULL
#define MCB2(FCT,FN) MCB(FCT,FSL_CKUP_RM_NOT,FN)
  /************************************************************************
  ** All of the information needed to do the merge is now contained in the
  ** FV table.  Starting here, we begin to actually carry out the merge.
  **
  ** First, find files in M and V but not in P and report conflicts.
  ** The file in M will be ignored.  It will be treated as if it
  ** does not exist.
  */
  rc = fsl_cx_prepare(f, &q, "SELECT idm FROM " FSL__TABLE_FVM
                      " WHERE idp=0 AND idv>0 AND idm>0");
  if(rc) goto end;
  while( 0==rc && FSL_RC_STEP_ROW==(rc = fsl_stmt_step(&q)) ){
    fsl_id_t const idm = fsl_stmt_g_id(&q, 0);
    rc = fsl_cx_exec(f, "UPDATE " FSL__TABLE_FVM
                     " SET idm=0 WHERE idm=%" FSL_ID_T_PFMT, idm);
    if(0==rc && opt->callback){
      fsl_buffer * const bName = fsl__cx_scratchpad(f);
      rc = fsl_db_get_buffer(db, bName, false,
                             "SELECT pathname FROM vfile WHERE id=%" FSL_ID_T_PFMT,
                             idm);
      if(0==rc){
        MCB2(FSL_MERGE_FCHANGE_CONFLICT_ANCESTOR,
             fsl_buffer_cstr(bName));
      }
      fsl__cx_scratchpad_yield(f, bName);
    }
  }
  fsl_stmt_finalize(&q);
  switch(rc){
    case 0:
    case FSL_RC_STEP_DONE: rc = 0; break;
    default: goto end;
  }

  /*
  ** Find files that have changed from P->M but not P->V.
  ** Copy the M content over into V.
  */
  rc = fsl_cx_prepare(f, &q,
    "SELECT idv, ridm, fn, islinkm FROM " FSL__TABLE_FVM
    " WHERE idp>0 AND idv>0 AND idm>0"
    "   AND ridm!=ridp AND ridv=ridp AND NOT chnged"
  );
  if(rc) goto end;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|







810
811
812
813
814
815
816































817
818
819
820
821
822
823
824
825
  rc = opt->callback(&mState); \
  mState.priorName = NULL
#define MCB2(FCT,FN) MCB(FCT,FSL_CKUP_RM_NOT,FN)
  /************************************************************************
  ** All of the information needed to do the merge is now contained in the
  ** FV table.  Starting here, we begin to actually carry out the merge.
  **































  ** First, find files that have changed from P->M but not P->V.  Copy
  ** the M content over into V.
  */
  rc = fsl_cx_prepare(f, &q,
    "SELECT idv, ridm, fn, islinkm FROM " FSL__TABLE_FVM
    " WHERE idp>0 AND idv>0 AND idm>0"
    "   AND ridm!=ridp AND ridv=ridp AND NOT chnged"
  );
  if(rc) goto end;
888
889
890
891
892
893
894










895
896
897
898
899
900


901
902
903
904
905
906
907
    case 0:
    case FSL_RC_STEP_DONE: rc = 0; break;
    default: goto end;
  }

  /*
  ** Do a three-way merge on files that have changes on both P->M and P->V.










  */
  rc = fsl_cx_prepare(f, &q,
    "SELECT ridm, idv, ridp, ridv,"
    " FSL_GLOB('binary-glob'," FSL__TABLE_FVM ".fn),"
    " fn, isexe, islinkv, islinkm FROM " FSL__TABLE_FVM
    " WHERE idp>0 AND idv>0 AND idm>0"


    "   AND ridm!=ridp AND (ridv!=ridp OR chnged)"
  );
  if(0==rc){
    rc = fsl_buffer_append( absPath, f->ckout.dir, (fsl_int_t)f->ckout.dirLen);
  }
  while( 0==rc && (FSL_RC_STEP_ROW==fsl_stmt_step(&q)) ){
    fsl_id_t const ridm = fsl_stmt_g_id(&q, 0);







>
>
>
>
>
>
>
>
>
>





|
>
>







857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
    case 0:
    case FSL_RC_STEP_DONE: rc = 0; break;
    default: goto end;
  }

  /*
  ** Do a three-way merge on files that have changes on both P->M and P->V.
  **
  ** Proceed even if the file doesn't exist on P, as if the common
  ** ancestor of M and V is an empty file. In this case, merge
  ** conflict marks will be added to the file and the user will be
  ** forced to handle them like any other conflict. The alternative is
  ** that we warn the user via opt->callback and let them decide on
  ** whether to keep the copy from P->V (historical default behavior)
  ** or error out.  As of 2023-04, fossil treats this as a normal
  ** merge conflict with an empty common ancestor version, so we'll do
  ** the same.
  */
  rc = fsl_cx_prepare(f, &q,
    "SELECT ridm, idv, ridp, ridv,"
    " FSL_GLOB('binary-glob'," FSL__TABLE_FVM ".fn),"
    " fn, isexe, islinkv, islinkm FROM " FSL__TABLE_FVM
    " WHERE /*idp>0 AND*/ idv>0 AND idm>0"
    /* -----^^^^^^^^^^^^^ https://fossil-scm.org/home/info/7c75e47b3c130ff1
       With that clause, entries with no common ancestor are filtered out. */
    "   AND ridm!=ridp AND (ridv!=ridp OR chnged)"
  );
  if(0==rc){
    rc = fsl_buffer_append( absPath, f->ckout.dir, (fsl_int_t)f->ckout.dirLen);
  }
  while( 0==rc && (FSL_RC_STEP_ROW==fsl_stmt_step(&q)) ){
    fsl_id_t const ridm = fsl_stmt_g_id(&q, 0);
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
      if(opt->debug){
        MARKER(("Merge: %s\n", zName));
      }
      absPath->used = f->ckout.dirLen;
      rc = fsl_buffer_append(absPath, zName, (fsl_int_t)nName);
      if(rc) break;
      zFullPath = fsl_buffer_cstr(absPath);
      rc = fsl_content_get(f, ridp, &p);
      if(0==rc) rc = fsl_content_get(f, ridm, &m);
      if(0==rc){
        //unsigned mergeFlags = dryRunFlag ? MERGE_DRYRUN : 0;
        //if(keepMergeFlag!=0) mergeFlags |= MERGE_KEEP_FILES;
        //rc = merge_3way(&p, zFullPath, &m, &r, mergeFlags);
        unsigned int nConflict = 0;
        fsl_buffer * const contentLocal = fsl__cx_content_buffer(f);







|







923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
      if(opt->debug){
        MARKER(("Merge: %s\n", zName));
      }
      absPath->used = f->ckout.dirLen;
      rc = fsl_buffer_append(absPath, zName, (fsl_int_t)nName);
      if(rc) break;
      zFullPath = fsl_buffer_cstr(absPath);
      if(ridp) rc = fsl_content_get(f, ridp, &p);
      if(0==rc) rc = fsl_content_get(f, ridm, &m);
      if(0==rc){
        //unsigned mergeFlags = dryRunFlag ? MERGE_DRYRUN : 0;
        //if(keepMergeFlag!=0) mergeFlags |= MERGE_KEEP_FILES;
        //rc = merge_3way(&p, zFullPath, &m, &r, mergeFlags);
        unsigned int nConflict = 0;
        fsl_buffer * const contentLocal = fsl__cx_content_buffer(f);