Login
Changes On Branch broke-r-card
Login

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

Changes In Branch broke-r-card Excluding Merge-Ins

This is equivalent to a diff from aeee30c289 to 6df1e4338a

2013-08-24
08:57
Pulled in fixed broke-r-card branch. f-mfparse now reads from stdin by default if no -f or filename is provided and it is not on a terminal. check-in: 6d746e7d25 user: stephan tags: trunk
08:54
Partial revert of the last commit (problem was the va_list/sizeof/snprintf() weirdness again). More experimentation with that particular problem - not sure why it's specific to sprintf(). Closed-Leaf check-in: 6df1e4338a user: stephan tags: broke-r-card
07:44
minor cleanups. fixed f-mfparse to know the difference between an imported/artifical artifact and a known own, and skips the sha1 check on imported ones. fsl_deck_parse() no longer asserts if it cannot find a matching RID. check-in: f26b454fa1 user: stephan tags: broke-r-card
2013-08-23
21:31
Events have W-cards too, so this needs to be checked first. check-in: aeee30c289 user: jan.nijtmans tags: trunk
18:45
prettied up the output a bit. check-in: 56237933d2 user: stephan tags: trunk

Changes to f-event.c.
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167



168
169
170
171












172
173
174
175
176
177
178
179
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164




165
166
167
168



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188







+














-
-
-
-
+
+
+

-
-
-
+
+
+
+
+
+
+
+
+
+
+
+








    Enable 'long long'
    typedef fsl_int32_t fsl_id_t
    #define FSL_ID_T_PFMT FSL_INT32_T_PFMT

    And then...
  */
  {
    char buf[80];
    int i = 0;
    f_out(("#%d: %"FSL_ID_T_PFMT" %"FSL_ID_T_PFMT" %"FSL_ID_T_PFMT"\n",
           ++i, 1, 2, 3));
    f_out(("#%d: %"FSL_SIZE_T_PFMT" %"FSL_ID_T_PFMT" %"FSL_SIZE_T_PFMT"\n",
           ++i, (fsl_size_t)1, (fsl_id_t)2, (fsl_size_t)3));
    puts("This next one fails badly because the numeric arguments "
         "are passed on as integers and the va_arg() handling extracts "
         "a larger type, effectively skipping over arguments and potentially "
         "overrunning memory (i.e. corruption):");
    f_out(("#%d: %"FSL_SIZE_T_PFMT" %"FSL_ID_T_PFMT" %"FSL_SIZE_T_PFMT"\n",
           ++i, 1, 2, 3));
    puts("The trigger is the 'll' format specifier in conjunction with "
         "integer arguments which are not strongly typed and don't match "
         "their format specifier's expected sizeof() exactly.");
  }
  /*
    Problem has something to do with the sizeof(int) resp. sizeof(fsl_id_t)
    and the va_arg() handling of the etRADIX bits in fsl_appendf().
    /*
      Problem has something to do with the sizeof(int) resp. sizeof(fsl_id_t)
      and the va_arg() handling of the etRADIX bits in fsl_appendf().

    The fix? Find the right combination of formatting string for integers
    in that combination. %d is apparently not correct.
  */
      The fix? Find the right combination of formatting string for integers
      in that combination. %d is apparently not correct.

      And it only appears to happen when we cross multiple levels of va_list
      handling? Namely, it happens in fsl_snprintf() but not fsl_output():
    */
    fsl_snprintf(buf, sizeof(buf),
                 "#%d: %"FSL_SIZE_T_PFMT" %"FSL_ID_T_PFMT" %"FSL_SIZE_T_PFMT"\n",
                 ++i, (fsl_size_t)1, (fsl_id_t)2, (fsl_size_t)3);
    f_out(("fsl_snprintf() says: %s\n", buf));
    puts("That one is failing differently in tcc/gcc.");
  }
#else
  rc = test_event_0();
#endif
  
  end:
  return FossilApp_err_report(0)
    ? EXIT_FAILURE : rc;
}
Changes to f-mfparse.c.
101
102
103
104
105
106
107
108





109
110
111
112
113
114
115
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117
118
119







-
+
+
+
+
+







  }else{
    f_out(("Rather large - not dumping to console.\n"));
  }
  f_out(("Dumping mf to file [%s]\n", ofile));
  rc = fsl_buffer_to_filename(&bout, ofile);
  assert(!rc);
  seemsSafeEnough = 0;
  {
  if(!mf.uuid){
    assert(0==mf.rid);
    f_out(("This _appears_ to be an imported/artificial manifest. "
           "Skipping UUID/SHA1 check.\n"));
  }else{
    fsl_buffer sha = fsl_buffer_empty;
    rc = fsl_sha1sum_filename(ofile, &sha);
    assert(!rc);
    f_out(("SHA of [%s] = [%b]\n", ofile, &sha));
    seemsSafeEnough = (0==fsl_strcmp(fsl_buffer_cstr(&sha),
                                     mf.uuid));
    f_out(("SHA match? %s\n",
Changes to include/fossil-scm/fossil.h.
2899
2900
2901
2902
2903
2904
2905



2906
2907
2908
2909
2910
2911
2912
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915







+
+
+








  /**
   ** va_list counterpart to fsl_mprintf().
   */
  char * fsl_mprintfv(char const * fmt, va_list vargs );

  /**
   ** DO NOT USE: seeing corruption involving sizeof(int-types) with
   ** some specifiers when crossing multiple va_list boundaries here.
   **
   ** An sprintf(3) clone which uses fsl_appendf() for the formatting.
   ** Outputs at most n bytes to dest and returns the number
   ** of bytes output. Returns a negative value if !dest or !fmt. Returns 0
   ** without side-effects if !n or !*fmt.
   **
   ** If the destination buffer is long enough (this function returns
   ** a non-negative value less than n), this function NUL-terminates it.
Changes to src/fsl_mf.c.
738
739
740
741
742
743
744
745

746
747
748
749
750

751
752
753
754
755
756
757
758
759
760
761

762
763
764

765
766
767
768
769
770
771
772
738
739
740
741
742
743
744

745
746




747











748



749

750
751
752
753
754
755
756







-
+

-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-







      fsl_md5_update_cstr(&md5, fc->name, -1);
      rc = fsl_repo_content_get(f, fileRid, &buf);
      if(rc){
        goto end;
      }
      numBuf[0] = 0;
#if 1
      sprintf(numBuf, " %"FSL_SIZE_T_PFMT"\n", buf.used);
      snprintf(numBuf, NumBufSize, " %u\n", (unsigned)buf.used);
#else
      /* WEIRD bug: numBuf is being populated with 140734393250192 if
         i use %FSL_SIZE_T_PFMT, 2982236112 if use %u, -1519416576 if
         i use %d.
         
      /* Awaiting portable bugfix for sizeof()/format-string combination */
         The same formatting bugs go through fsl_outputf() just fine
         (and that all goes through the same place formatting
         routine).

         The bug appears to be in fsl_appendfv() (because the appendfv
         callback gets the memory that way), and it might be related
         to sizeof(long long) being 8 on this particular environment
         and the va_arg conversion doing something funky there. Fall
         back to sprintf() for now.
      */
      fsl_snprintf(numBuf, NumBufSize, " %d\n", (int)buf.used);
      fsl_snprintf(numBuf, NumBufSize, " %"FSL_SIZE_T_PFMT"\n", buf.used);
      /* Broken: fsl_snprintf(numBuf, NumBufSize, " %u\n", (unsigned)buf.used);*/
      /* Broken: fsl_snprintf(numBuf, NumBufSize, "%"FSL_SIZE_T_PFMT"\n", (int)buf.used); */
      /* MARKER(("buf.used=%"FSL_SIZE_T_PFMT", numBuf=%s\n",buf.used, numBuf )); */
      if(0) MARKER(("numbuf=[%s]\n", numBuf));
      fsl_outputf(f, "buf.used=%"FSL_SIZE_T_PFMT", numBuf=%s",buf.used, numBuf );
#endif
      fsl_md5_update_cstr(&md5, numBuf, -1);
      fsl_md5_update_buffer(&md5, &buf);
    }
    if(!rc){
      fsl_md5_final(&md5, digest);
      fsl_md5_digest_to_base16(digest, hex);
937
938
939
940
941
942
943
944


945
946
947
948

949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966


967
968
969
970
971


972
973

974
975


976
977
978
979
980

981
982

983
984
985
986
987
988
989
921
922
923
924
925
926
927

928
929
930
931
932

933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950

951
952
953
954
955


956
957
958
959
960
961

962
963
964
965
966
967
968
969
970

971
972
973
974
975
976
977
978







-
+
+



-
+

















-
+
+



-
-
+
+


+

-
+
+





+

-
+







    }
    return rc;
  }
}

  
/**
 ** Output state for fsl_appendf_f_mf() and friends.
 ** Output state for fsl_appendf_f_mf() and friends. Used for managing
 ** the output of a fsl_deck.
 */
struct fsl_deck_out_state {
  /**
   ** Checkout db handle. Needed for certain card generation bits.
   ** Repo db handle. Needed for certain card generation bits.
   */
  fsl_db * db;
  /**
   ** The set of cards being output. We use this to delegate certain
   ** output bits.
   */
  fsl_deck const * cards;
  /**
   ** Output routine to send manifest to.
   */
  fsl_output_f out;
  /**
   ** State to pass as the first arg of this->out().
   */
  void * outState;
  /**
   ** f() result code, so that we can feed the code back through the
   ** fsl_appendf() layer. If this is non-0, processing must stop.
   ** fsl_appendf() layer. If this is non-0, processing must stop.  We
   ** "could" use this->error.code instead, but this is simple.
   */
  int rc;
  /**
   ** Counter for list-visiting routines. Must be re-set
   ** before each visit loop.
   ** Counter for list-visiting routines. Must be re-set before each
   ** visit loop if the visitor makes use of this (most do not).
   */
  fsl_int_t counter;

  /**
   ** MD5 sum of all output sent via fsl_appendf_f_mf().
   ** Incrementally-calculated MD5 sum of all output sent via
   ** fsl_appendf_f_mf().
   */
  fsl_md5_cx md5;

  /* Holds error state for propagating back to the client. */
  fsl_error error;

  /**
   ** Buffer for fossilzing bytes.
   ** Scratch buffer for fossilzing bytes and other temporary work.
   */
  fsl_buffer scratch;
};
typedef struct fsl_deck_out_state fsl_deck_out_state;
static const fsl_deck_out_state fsl_deck_out_state_empty = {
NULL/*db*/,
NULL/*cards*/,
1043
1044
1045
1046
1047
1048
1049




1050
1051
1052
1053
1054
1055
1056
1057
1058

1059
1060
1061
1062
1063
1064
1065
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050

1051
1052
1053
1054
1055
1056
1057
1058







+
+
+
+








-
+







                               fsl_int_t len){
  fsl_buffer_reset(&os->scratch);
  return os->rc = len
    ? fsl_bytes_fossilize(inp, len, &os->scratch)
    : 0;
}

/**
 ** Fossilizes b->mem to os->scratch. Returns 0 on success and all
 ** that.
 */
static int fsl_deck_fossilize_b( fsl_deck_out_state * os,
                                 fsl_buffer const * b ){
  return b->used
    ? fsl_deck_fossilize( os, b->mem, (fsl_int_t)b->used)
    : 0;
}
/**
 ** If doFossilize, fossilizes b to os->scratch and passes that result
 ** to fsl_deck_append(), otherwise ises b's contents directly for
 ** to fsl_deck_append(), otherwise uses b's contents directly for
 ** appending a card (with the given letter) to os:
 **
 ** LETTER CONTENT\\n
 **
 ** This is only useful for cards with simple buffer values.
 */
static int fsl_deck_out_letter_buf( fsl_deck_out_state * os,
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528



1529
1530
1531
1532
1533
1534
1535
1536
1537

1538
1539
1540
1541
1542

1543
1544
1545
1546
1547
1548
1549
1512
1513
1514
1515
1516
1517
1518



1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529

1530
1531
1532
1533
1534

1535
1536
1537
1538
1539
1540
1541
1542







-
-
-
+
+
+








-
+




-
+







static int fsl_deck_out_T( fsl_deck_out_state * os ){
  return fsl_deck_out_list_obj(os, &os->cards->T,
                                  fsl_list_v_mf_output_card_T);
}

static int fsl_deck_out_W( fsl_deck_out_state * os ){
  if(os->cards->W.used){
    os->rc = fsl_deck_append(os, "W %"FSL_SIZE_T_PFMT"\n%b\n",
                             os->cards->W.used,
                             &os->cards->W );
    fsl_deck_append(os, "W %"FSL_SIZE_T_PFMT"\n%b\n",
                    os->cards->W.used,
                    &os->cards->W );
  }
  return os->rc;
}


/* Appends the Z card to os from os' accummulated md5 hash. */
static int fsl_deck_out_Z( fsl_deck_out_state * os ){
  unsigned char digest[16];
  char md5[33];
  char md5[FSL_MD5_STRLEN+1];
  fsl_md5_final(&os->md5, digest);
  fsl_md5_digest_to_base16(digest, md5);
  assert(!md5[32]);
  os->md5.isInit = 0 /* Keep further output from updating the MD5 */;
  return fsl_deck_append(os, "Z %.*s\n", 32, md5);
  return fsl_deck_append(os, "Z %.*s\n", FSL_MD5_STRLEN, md5);
}

static char fsl_deck_check_required_cards(fsl_cx *f,
                                          fsl_deck const * d){
  if(fsl_deck_has_required_cards(d)) return 1;
  else{
    fsl_cx_err_set(f, FSL_RC_MF_SYNTAX,
1568
1569
1570
1571
1572
1573
1574

1575
1576
1577
1578
1579
1580
1581
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575







+








static int fsl_deck_output_cluster( fsl_deck_out_state * os ){
  return fsl_deck_out_list_obj(os, &os->cards->M,
                                  fsl_list_v_mf_output_card_M);
}


/* Helper for fsl_deck_output_CATYPE() */
#define DOUT(LETTER) rc = fsl_deck_out_##LETTER(os); \
  if(rc || os->rc) return os->rc ? os->rc : rc

static int fsl_deck_output_control( fsl_deck_out_state * os ){
  int rc;
  /* Reminder: cards must be output in strict lexical order. */
  DOUT(D);
1693
1694
1695
1696
1697
1698
1699
1700


1701
1702
1703
1704
1705
1706
1707
1687
1688
1689
1690
1691
1692
1693

1694
1695
1696
1697
1698
1699
1700
1701
1702







-
+
+







}

int fsl_deck_output( fsl_cx * f, fsl_deck const * cards,
                     fsl_output_f out, void * outputState ){
  static const char allowTypeAny = 0
    /* Only enable for debugging/testing. Allows outputing decks of
    ** type FSL_CATYPE_ANY, which bypasses some validation checks and
    ** may trigger other validation assertions.
    ** may trigger other validation assertions. And may allow you to
    ** inject garbage into the repo. So be careful.
    */;

  fsl_deck_out_state OS = fsl_deck_out_state_empty;
  fsl_deck_out_state * os = &OS;
  int rc = 0;
  fsl_db * db = fsl_cx_db_repo(f);
  if(!cards || !out || !f || !db) return FSL_RC_MISUSE;
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1823
1824
1825
1826
1827
1828
1829




1830
1831
1832
1833
1834
1835
1836







-
-
-
-







  fsl_stmt * s1 = NULL;
  int rc;
  assert(f);
  assert(db);
  assert(db->beginCount>0);
  rc = fsl_repo_filename_to_fnid(f, zFilename, &fnid);
  if(rc) return rc;
  /*
    MISSING: uuid_to_rid()'s second argument determines
    whether to create phantom artifacts or not.
  */
  if( zPrior && *zPrior ){
    rc = fsl_repo_filename_to_fnid(f, zPrior, &pfnid);
    if(rc) return rc;
  }else{
    pfnid = 0;
  }
  if( zFromUuid && *zFromUuid ){
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948





1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963

1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981

1982
1983
1984
1985
1986
1987
1988
1930
1931
1932
1933
1934
1935
1936



1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955

1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982







-
-
-
+
+
+
+
+














-
+


















+







#undef FCARD
}

/**
 ** Locate a file named zName in d->F.list.  Return a pointer to the
 ** appropriate fsl_mf_card object. Return NULL if not found.
 **
 ** This routine works even if p is a delta-manifest. The pointer 
 ** returned might be to the baseline and d->B.baseline is loaded
 ** on demand if needed.
 ** This routine works even if p is a delta-manifest. The pointer
 ** returned might be to the baseline and d->B.baseline is loaded on
 ** demand if needed. It returns NULL if it finds a match but that
 ** match has no UUID, indicating that it was removed from the tree by
 ** this manifest.
 **
 ** We assume that filenames are in sorted order and use a binary
 ** search.
 */
fsl_mf_fcard const * fsl_deck_F_seek(fsl_deck * d, const char *zName){
  fsl_mf_fcard const *pFile;
  again:
  pFile = fsl_deck_F_seek_base(d, zName);
  if( pFile && !pFile->uuid ) return NULL
    /* File was removed from repo in this manifest. (i think?) */
    ;
  else if( !pFile && d && d->B.uuid ){
    /* Recursively check baseline manifests... */
    int rc;
    assert(!"force caller to load baseline so this op can be const.");
    /* assert(!"force caller to load baseline so this op can be const."); */
    rc = fsl_deck_baseline_fetch(d);
    if(rc){
      assert(d->f->error.code);
    }else if( (d = d->B.baseline) ) goto again;
  }
  return pFile;
}

/**
 ** fsl_list_visitor_f() state for fsl_deck_F_find().
 */
struct FCardSearch {
  /** Filename to match against */
  char const * str;
  /** On success, this is set to the found object. */
  fsl_mf_fcard const * fc;
};
typedef struct FCardSearch FCardSearch;

/**
 ** A fsl_list_visitor_f() impl which performs a case-insensitive
 ** search for a file. state must be a (FCardSearch*). state->str
 ** is the string to search for. On success, FSL_RC_BREAK is returned
 ** and state->fc will point to the F-card which was found.
 */
static int fsl_list_v_fsl_mf_F_search_nocase(void * obj, void * state ){
1997
1998
1999
2000
2001
2002
2003
2004

2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015

2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
1991
1992
1993
1994
1995
1996
1997

1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008

2009
2010
2011
2012
2013
2014
2015
2016
2017
2018


2019
2020
2021
2022
2023
2024
2025







-
+










-
+









-
-







}

/**
 ** Look for a file in a manifest, taking the case-insensitive option
 ** into account.  If case-insensitive is on then files in any case
 ** will match.
 */
/*static*/
/* static */
fsl_mf_fcard const * fsl_deck_F_find(fsl_deck *d, const char *zName){
  assert(d->f);
  if( !d->f->cache.caseInsensitive ) return fsl_deck_F_seek(d, zName);
  else{
    FCardSearch state;
    state.str = zName;
    state.fc = NULL;
    while(d && !state.fc){
      fsl_list_visit(&d->F.list, 0, fsl_list_v_fsl_mf_F_search_nocase, &state);
      if(!state.fc && d->B.uuid){
        assert(!"force caller to load baseline so this op can be const.");
        /* assert(!"force caller to load baseline so this op can be const."); */
        fsl_deck_baseline_fetch(d);
        d = d->B.baseline;
      }
    }
    return state.fc;
  }
}

/**
 ** INCOMPLETE.
 **
 ** Add mlink table entries associated with manifest cid, pChild.  The
 ** parent manifest is pid, pParent.  One of either pChild or pParent
 ** will be NULL and it will be computed based on cid/pid.
 **
 ** A single mlink entry is added for every file that changed content,
 ** name, and/or permissions going from pid to cid.
 **
2455
2456
2457
2458
2459
2460
2461
2462

2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475


2476

2477
2478
2479







2480
2481

2482

2483

2484
2485
2486
2487
2488
2489
2490
2491
2492

2493
2494
2495
2496
2497
2498
2499
2447
2448
2449
2450
2451
2452
2453

2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469

2470



2471
2472
2473
2474
2475
2476
2477


2478
2479
2480

2481
2482
2483
2484
2485
2486
2487
2488
2489

2490
2491
2492
2493
2494
2495
2496
2497







-
+













+
+
-
+
-
-
-
+
+
+
+
+
+
+
-
-
+

+
-
+








-
+







  else if( d->type==FSL_CATYPE_WIKI ){
    fsl_buffer buf = fsl_buffer_empty;
    fsl_id_t tagid;
    fsl_id_t prior;
    char zLength[40] = {0};
    char const * zWiki;
    char const * zTag;
    fsl_size_t nWiki;
    fsl_size_t nWiki = 0;
    rc = fsl_buffer_appendf(&buf, "wiki-%b", &d->L);
    if(rc) goto wiki_end;
    zTag = fsl_buffer_cstr(&buf);
    tagid = fsl_repo_tag_id( f, zTag, 1 );
    if(tagid<=0){
      rc = f->error.code ? f->error.code :
        fsl_cx_err_set(f, FSL_RC_RANGE,
                       "Got unexpected RID (%"FSL_ID_T_PFMT") "
                       "for tag [%s].",
                       tagid, zTag);
      goto wiki_end;
    }
    zWiki = d->W.used ? fsl_buffer_cstr(&d->W) : "";
    while( *zWiki && fsl_isspace(*zWiki) ){
      ++zWiki;
    /* Historical behaviour: strip leading spaces. */
      /* Historical behaviour: strip leading spaces. */
    while( *zWiki && fsl_isspace(*zWiki) ) ++zWiki;
    nWiki = fsl_strlen(zWiki);
#if 0
    }
    nWiki = fsl_strlen(zWiki)
      /* Reminder: use strlen instead of d->W.used in case
         just in case that one contains embedded NULs
         in the content.
      */;
#if 1
    /* Awaiting a bug fix. */
    fsl_snprintf( zLength, sizeof(zLength), "%"FSL_SIZE_T_PFMT, nWiki);
    snprintf(zLength, sizeof(zLength), " %"FSL_SIZE_T_PFMT, nWiki);
#else
    /* Awaiting portable bugfix for sizeof()/format-string combination */
    sprintf( zLength, "%"FSL_SIZE_T_PFMT, nWiki);
    fsl_snprintf( zLength, sizeof(zLength), "%"FSL_SIZE_T_PFMT, nWiki);
#endif
    rc = fsl_repo_tag_insert(f, FSL_TAGTYPE_ADD, zTag, zLength,
                             rid, d->D, rid, NULL );
    if(rc) goto wiki_end;
    buf.used = 0 /* re-use memory for comment text */;
    zTag = zWiki = NULL;
    prior = fsl_db_g_id(db, 0,
      "SELECT rid FROM tagxref"
      " WHERE tagid=%"FSL_ID_T_PFMT" AND mtime<%"FSL_JULIAN_T_PFMT""
      " WHERE tagid=%"FSL_ID_T_PFMT" AND mtime<%"FSL_JULIAN_T_PFMT
      " ORDER BY mtime DESC",
      tagid, d->D
    );
    if(prior>0){
      rc = fsl_repo_content_deltify(f, prior, rid, 0);
      if(rc) goto wiki_end;
    }
2538
2539
2540
2541
2542
2543
2544
2545

2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558


2559

2560

2561
2562

2563
2564

2565

2566

2567
2568
2569
2570
2571
2572
2573
2536
2537
2538
2539
2540
2541
2542

2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558

2559

2560
2561

2562


2563
2564
2565

2566
2567
2568
2569
2570
2571
2572
2573







-
+













+
+
-
+
-
+

-
+
-
-
+

+
-
+







  if( d->type==FSL_CATYPE_EVENT ){
    fsl_buffer buf = fsl_buffer_empty;
    fsl_id_t tagid;
    fsl_id_t prior, subsequent;
    char zLength[40] = {0};
    char const * zWiki;
    char const * zTag;
    fsl_size_t nWiki;
    fsl_size_t nWiki = 0;
    rc = fsl_buffer_appendf(&buf, "event-%b", &d->E.uuid);
    if(rc) goto wiki_end;
    zTag = fsl_buffer_cstr(&buf);
    tagid = fsl_repo_tag_id( f, zTag, 1 );
    if(tagid<=0){
      rc = f->error.code ? f->error.code :
        fsl_cx_err_set(f, FSL_RC_RANGE,
                       "Got unexpected RID (%"FSL_ID_T_PFMT") "
                       "for tag [%s].",
                       tagid, zTag);
      goto event_end;
    }
    zWiki = d->W.used ? fsl_buffer_cstr(&d->W) : "";
    while( *zWiki && fsl_isspace(*zWiki) ){
      ++zWiki;
    /* Historical behaviour: strip leading spaces. */
      /* Historical behaviour: strip leading spaces. */
    while( *zWiki && fsl_isspace(*zWiki) ) ++zWiki;
    }
    nWiki = fsl_strlen(zWiki);
#if 0
#if 1
    /* Awaiting a bug fix. */
    fsl_snprintf( zLength, sizeof(zLength), "%"FSL_SIZE_T_PFMT, nWiki);
    snprintf(zLength, sizeof(zLength), " %"FSL_SIZE_T_PFMT, nWiki);
#else
    /* Awaiting portable bugfix for sizeof()/format-string combination */
    sprintf( zLength, "%"FSL_SIZE_T_PFMT, nWiki);
    fsl_snprintf( zLength, sizeof(zLength), "%"FSL_SIZE_T_PFMT, nWiki);
#endif
    rc = fsl_repo_tag_insert(f, FSL_TAGTYPE_ADD, zTag, zLength,
                             rid, d->D, rid, NULL );
    if(rc) goto event_end;
    prior = fsl_db_g_id(db, 0,
                       "SELECT rid FROM tagxref"
                       " WHERE tagid=%"FSL_ID_T_PFMT
3549
3550
3551
3552
3553
3554
3555
3556
3557




3558
3559
3560
3561
3562
3563





3564
3565
3566
3567
3568
3569
3570
3549
3550
3551
3552
3553
3554
3555


3556
3557
3558
3559






3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571







-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+







         FSL_CATYPE_CONTROL==d->type ||
         FSL_CATYPE_WIKI==d->type ||
         FSL_CATYPE_TICKET==d->type ||
         FSL_CATYPE_ATTACHMENT==d->type ||
         FSL_CATYPE_EVENT==d->type);

  d->rid = fsl_repo_uuid_to_rid(f, fsl_buffer_cstr(&selfHash));
  assert(d->rid>0);
  if(d->rid<=0){
  /* assert(d->rid>0);
     can't run test manifest through this if we assert here.
   */
  if(d->rid>0){
    assert(f->error.code);
    goto bailout;
  }
    
  fsl_free(d->uuid);
  d->uuid = fsl_buffer_str(&selfHash) /* transfer ownership */;
    fsl_free(d->uuid);
    d->uuid = fsl_buffer_str(&selfHash) /* transfer ownership */;
  }else{
    fsl_buffer_clear(&selfHash);
  }
  return rc;

  bailout:
  assert(0 != rc);
  fsl_buffer_clear(&selfHash);
  if(zMsg){
    rc = fsl_cx_err_set(f, rc, "%s", zMsg);