Fossil

Changes On Branch hash-if-mtime-is-current
Login

Changes On Branch hash-if-mtime-is-current

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

Changes In Branch hash-if-mtime-is-current Excluding Merge-Ins

This is equivalent to a diff from c8fda6a6 to 1cd36fad

2024-01-13
18:57
Typo in variable name. (Leaf check-in: 1cd36fad user: preben tags: hash-if-mtime-is-current)
2024-01-11
16:55
When reverting or updating a file, set the mtime to 0 as already done with merge and stash. Effectively, we don't trust the hash until next time we evaluate the status of the file, at which point we'll update vfile.mtime with the real mtime of the file.

Based on discussions in forum thread 58bef43842be6fc3. (check-in: f9686d02 user: preben tags: hash-if-mtime-is-current)

2024-01-07
17:26
Back out [a402dd2a888d6d74] (wiki title search), as it causes all searches to fail for reasons as yet undetermined. (check-in: 48af08bd user: stephan tags: trunk)
11:26
Compute hash if mtime is unchanged but match system time. Discussed in forum thread 58bef43842be6fc3. (check-in: b295f86d user: preben tags: hash-if-mtime-is-current)
2024-01-05
21:02
Add more information when user encounters an Unresolved RID condition. (check-in: c8fda6a6 user: preben tags: trunk)
2024-01-04
10:34
Update stash test for the recently integrated diff-deleted-files branch. (check-in: bc9e84bb user: preben tags: trunk)
2023-11-16
12:16
Add more information when user encounters an Unresolved RID condition. (Closed-Leaf check-in: c04e494d user: preben tags: unresolved-rid-explanation)

Changes to src/merge.c.

216
217
218
219
220
221
222
223
224
225
226
227
228
229

230
231
232
233
234
235
236
  db_finalize(&q);
}

/*
** Print the content of the VFILE table on standard output, for
** debugging purposes.
*/
static void debug_show_vfile(void){
  Stmt q;
  int pvid = -1;
  db_prepare(&q,
    "SELECT vid, id, chnged, deleted, isexe, islink, rid, mrid, mtime,"
          " pathname, origname, mhash FROM vfile"
    " ORDER BY vid, pathname"

  );
  while( db_step(&q)==SQLITE_ROW ){
    int vid = db_column_int(&q, 0);
    int chnged = db_column_int(&q, 2);
    int dltd = db_column_int(&q, 3);
    int isexe = db_column_int(&q, 4);
    int islnk = db_column_int(&q, 5);







|




|
|
>







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
  db_finalize(&q);
}

/*
** Print the content of the VFILE table on standard output, for
** debugging purposes.
*/
static void debug_show_vfile(int showAll){
  Stmt q;
  int pvid = -1;
  db_prepare(&q,
    "SELECT vid, id, chnged, deleted, isexe, islink, rid, mrid, mtime,"
          " pathname, origname, mhash, %s FROM vfile"
    " ORDER BY vid, pathname",
    showAll ? "COALESCE(datetime(mtime, 'unixepoch', 'localtime'), 'NULL')" : "''"
  );
  while( db_step(&q)==SQLITE_ROW ){
    int vid = db_column_int(&q, 0);
    int chnged = db_column_int(&q, 2);
    int dltd = db_column_int(&q, 3);
    int isexe = db_column_int(&q, 4);
    int islnk = db_column_int(&q, 5);
250
251
252
253
254
255
256




257
258
259
260
261
262
263
264



265
266
267

268
269
270
271
272
273
274
275
276
277
278
279
280
       isexe  ? "exe" : "",
       islnk  ? "lnk" : "", zPath);
    if( zOrig && zOrig[0] ){
      fossil_print(" <- %s\n", zOrig);
    }else{
      fossil_print("\n");
    }




  }
  db_finalize(&q);
}

/*
** COMMAND: test-show-vfile
** Usage:  %fossil test-show-vfile
**



** Show the content of the VFILE table in a local check-out.
*/
void test_show_vfile_cmd(void){

  if( g.argc!=2 ){
    fossil_fatal("unknown arguments to the %s command\n", g.argv[1]);
  }
  verify_all_options();
  db_must_be_within_tree();
  debug_show_vfile();  
}


/*
** COMMAND: merge
** COMMAND: cherry-pick
**







>
>
>
>








>
>
>



>





|







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
       isexe  ? "exe" : "",
       islnk  ? "lnk" : "", zPath);
    if( zOrig && zOrig[0] ){
      fossil_print(" <- %s\n", zOrig);
    }else{
      fossil_print("\n");
    }
    if( showAll ){
      fossil_print("   mtime %19s / %-10i  mhash %s\n", db_column_text(&q, 12),
          db_column_int(&q , 8), db_column_text(&q, 11));
    }
  }
  db_finalize(&q);
}

/*
** COMMAND: test-show-vfile
** Usage:  %fossil test-show-vfile
**
** Options:
**   --all                   Show all fields
**
** Show the content of the VFILE table in a local check-out.
*/
void test_show_vfile_cmd(void){
  int showVfileAll = find_option("mtime",0,0)!=0;
  if( g.argc!=2 ){
    fossil_fatal("unknown arguments to the %s command\n", g.argv[1]);
  }
  verify_all_options();
  db_must_be_within_tree();
  debug_show_vfile(showVfileAll);  
}


/*
** COMMAND: merge
** COMMAND: cherry-pick
**
331
332
333
334
335
336
337

338
339
340
341
342
343
344
  int dryRunFlag;       /* True if the --dry-run or -n option is present */
  int forceFlag;        /* True if the --force or -f option is present */
  int forceMissingFlag; /* True if the --force-missing option is present */
  const char *zBinGlob; /* The value of --binary */
  const char *zPivot;   /* The value of --baseline */
  int debugFlag;        /* True if --debug is present */
  int showVfileFlag;    /* True if the --show-vfile flag is present */

  int keepMergeFlag;    /* True if --keep-merge-files is present */
  int nConflict = 0;    /* Number of conflicts seen */
  int nOverwrite = 0;   /* Number of unmanaged files overwritten */
  char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */
  Stmt q;









>







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  int dryRunFlag;       /* True if the --dry-run or -n option is present */
  int forceFlag;        /* True if the --force or -f option is present */
  int forceMissingFlag; /* True if the --force-missing option is present */
  const char *zBinGlob; /* The value of --binary */
  const char *zPivot;   /* The value of --baseline */
  int debugFlag;        /* True if --debug is present */
  int showVfileFlag;    /* True if the --show-vfile flag is present */
  int showVfileAll;     /* True if the --show-vfile-all flag is present */
  int keepMergeFlag;    /* True if --keep-merge-files is present */
  int nConflict = 0;    /* Number of conflicts seen */
  int nOverwrite = 0;   /* Number of unmanaged files overwritten */
  char vAncestor = 'p'; /* If P is an ancestor of V then 'p', else 'n' */
  Stmt q;


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
  if( !dryRunFlag ){
    dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
  }
  forceFlag = find_option("force","f",0)!=0;
  zPivot = find_option("baseline",0,1);
  keepMergeFlag = find_option("keep-merge-files", "K",0)!=0;

  /* Undocumented --debug and --show-vfile options:
  **
  ** When included on the command-line, --debug causes lots of state
  ** information to be displayed.  This option is undocumented as it
  ** might change or be eliminated in future releases.
  **
  ** The --show-vfile flag does a dump of the VFILE table for reference. 

  **
  ** Hints:
  **   *  Combine --debug and --verbose for still more output.
  **   *  The --dry-run option is also useful in combination with --debug.
  */
  debugFlag = find_option("debug",0,0)!=0;
  if( debugFlag && verboseFlag ) debugFlag = 2;
  showVfileFlag = find_option("show-vfile",0,0)!=0;


  verify_all_options();
  db_must_be_within_tree();
  if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("nothing is checked out");







|






>








>







377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
  if( !dryRunFlag ){
    dryRunFlag = find_option("nochange",0,0)!=0; /* deprecated */
  }
  forceFlag = find_option("force","f",0)!=0;
  zPivot = find_option("baseline",0,1);
  keepMergeFlag = find_option("keep-merge-files", "K",0)!=0;

  /* Undocumented --debug, --show-vfile, --show-vfile-all options:
  **
  ** When included on the command-line, --debug causes lots of state
  ** information to be displayed.  This option is undocumented as it
  ** might change or be eliminated in future releases.
  **
  ** The --show-vfile flag does a dump of the VFILE table for reference. 
  ** The --show-vfile-all shows all fields from the VFILE table.
  **
  ** Hints:
  **   *  Combine --debug and --verbose for still more output.
  **   *  The --dry-run option is also useful in combination with --debug.
  */
  debugFlag = find_option("debug",0,0)!=0;
  if( debugFlag && verboseFlag ) debugFlag = 2;
  showVfileFlag = find_option("show-vfile",0,0)!=0;
  showVfileAll = find_option("show-vfile-all",0,0)!=0;

  verify_all_options();
  db_must_be_within_tree();
  if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
  vid = db_lget_int("checkout", 0);
  if( vid==0 ){
    fossil_fatal("nothing is checked out");
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
    fossil_print("P=%-4d %z (file content pivot)\n", pid, z);
    z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
    fossil_print("M=%-4d %z (merged-in version)\n", mid, z);
    z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
    fossil_print("V=%-4d %z (current version)\n", vid, z);
    fossil_print("vAncestor = '%c'\n", vAncestor);
  }
  if( showVfileFlag ) debug_show_vfile();

  /*
  ** 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 check-out, the pivot, and the version being merged.
  */
  db_multi_exec(







|







565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
    fossil_print("P=%-4d %z (file content pivot)\n", pid, z);
    z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", mid);
    fossil_print("M=%-4d %z (merged-in version)\n", mid, z);
    z = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", vid);
    fossil_print("V=%-4d %z (current version)\n", vid, z);
    fossil_print("vAncestor = '%c'\n", vAncestor);
  }
  if( showVfileFlag || showVfileAll ) debug_show_vfile(showVfileAll);

  /*
  ** 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 check-out, the pivot, and the version being merged.
  */
  db_multi_exec(

Changes to src/update.c.

944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
        " WHERE pathname=%Q AND origname!=pathname;"
        "DELETE FROM vfile WHERE pathname=%Q",
        zFile, zFile
      );
    }else if( file_unsafe_in_tree_path(zFull) ){
      /* Ignore this file */
    }else{
      sqlite3_int64 mtime;
      int rvChnged = 0;
      int rvPerm = manifest_file_mperm(pRvFile);

      /* Determine if reverted-to file is different than checked-out file. */
      if( pCoManifest && (pCoFile = manifest_file_find(pCoManifest, zFile)) ){
        rvChnged = manifest_file_mperm(pRvFile)!=rvPerm
                || fossil_strcmp(pRvFile->zUuid, pCoFile->zUuid)!=0;







<







944
945
946
947
948
949
950

951
952
953
954
955
956
957
        " WHERE pathname=%Q AND origname!=pathname;"
        "DELETE FROM vfile WHERE pathname=%Q",
        zFile, zFile
      );
    }else if( file_unsafe_in_tree_path(zFull) ){
      /* Ignore this file */
    }else{

      int rvChnged = 0;
      int rvPerm = manifest_file_mperm(pRvFile);

      /* Determine if reverted-to file is different than checked-out file. */
      if( pCoManifest && (pCoFile = manifest_file_find(pCoManifest, zFile)) ){
        rvChnged = manifest_file_mperm(pRvFile)!=rvPerm
                || fossil_strcmp(pRvFile->zUuid, pCoFile->zUuid)!=0;
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
      if( rvPerm==PERM_LNK ){
        symlink_create(blob_str(&record), zFull);
      }else{
        blob_write_to_file(&record, zFull);
      }
      file_setexe(zFull, rvPerm==PERM_EXE);
      fossil_print("REVERT   %s\n", zFile);
      mtime = file_mtime(zFull, RepoFILE);
      db_multi_exec(
         "UPDATE vfile"
         "   SET mtime=%lld, chnged=%d, deleted=0, isexe=%d, islink=%d,"
         "       mrid=rid, mhash=NULL"
         " WHERE pathname=%Q OR origname=%Q",
         mtime, rvChnged, rvPerm==PERM_EXE, rvPerm==PERM_LNK, zFile, zFile
      );
    }
    blob_reset(&record);
    free(zFull);
  }
  db_finalize(&q);
  undo_finish();
  db_end_transaction(0);

  /* Deallocate parsed manifest structures. */
  manifest_destroy(pRvManifest);
  manifest_destroy(pCoManifest);
}







<


|


|













969
970
971
972
973
974
975

976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
      if( rvPerm==PERM_LNK ){
        symlink_create(blob_str(&record), zFull);
      }else{
        blob_write_to_file(&record, zFull);
      }
      file_setexe(zFull, rvPerm==PERM_EXE);
      fossil_print("REVERT   %s\n", zFile);

      db_multi_exec(
         "UPDATE vfile"
         "   SET mtime=0, chnged=%d, deleted=0, isexe=%d, islink=%d,"
         "       mrid=rid, mhash=NULL"
         " WHERE pathname=%Q OR origname=%Q",
         rvChnged, rvPerm==PERM_EXE, rvPerm==PERM_LNK, zFile, zFile
      );
    }
    blob_reset(&record);
    free(zFull);
  }
  db_finalize(&q);
  undo_finish();
  db_end_transaction(0);

  /* Deallocate parsed manifest structures. */
  manifest_destroy(pRvManifest);
  manifest_destroy(pCoManifest);
}

Changes to src/vfile.c.

17
18
19
20
21
22
23

24
25
26
27
28
29
30
**
** Procedures for managing the VFILE table.
*/
#include "config.h"
#include "vfile.h"
#include <assert.h>
#include <sys/types.h>


/*
** The input is guaranteed to be a 40- or 64-character well-formed
** artifact hash.  Find its rid.
*/
int fast_uuid_to_rid(const char *zUuid){
  static Stmt q;







>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
**
** Procedures for managing the VFILE table.
*/
#include "config.h"
#include "vfile.h"
#include <assert.h>
#include <sys/types.h>
#include <time.h>

/*
** The input is guaranteed to be a 40- or 64-character well-formed
** artifact hash.  Find its rid.
*/
int fast_uuid_to_rid(const char *zUuid){
  static Stmt q;
168
169
170
171
172
173
174

175
176
177
178
179
180
181
**
** If the mtime is used, it is used only to determine if files are the same.
** If the mtime of a file has changed, we still examine the on-disk content
** to see whether or not the edit was a null-edit.
*/
void vfile_check_signature(int vid, unsigned int cksigFlags){
  int nErr = 0;

  Stmt q;
  int useMtime = (cksigFlags & CKSIG_HASH)==0
                    && db_get_boolean("mtime-changes", 1);

  db_begin_transaction();
  db_prepare(&q, "SELECT id, %Q || pathname,"
                 "       vfile.mrid, deleted, chnged, uuid, size, mtime,"







>







169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
**
** If the mtime is used, it is used only to determine if files are the same.
** If the mtime of a file has changed, we still examine the on-disk content
** to see whether or not the edit was a null-edit.
*/
void vfile_check_signature(int vid, unsigned int cksigFlags){
  int nErr = 0;
  time_t now = time(0);
  Stmt q;
  int useMtime = (cksigFlags & CKSIG_HASH)==0
                    && db_get_boolean("mtime-changes", 1);

  db_begin_transaction();
  db_prepare(&q, "SELECT id, %Q || pathname,"
                 "       vfile.mrid, deleted, chnged, uuid, size, mtime,"
240
241
242
243
244
245
246







247
248
249
250
251
252
253
254
      ** if --hash is used, check to see if they have been edited by
      ** looking at their artifact hashes */
      const char *zUuid = db_column_text(&q, 5);
      int nUuid = db_column_bytes(&q, 5);
      assert( origSize==currentSize );
      if( !hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 1;
    }







    if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4)){
      i64 desiredMtime;
      if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
        if( currentMtime!=desiredMtime ){
          file_set_mtime(zName, desiredMtime);
          currentMtime = file_mtime(zName, RepoFILE);
        }
      }







>
>
>
>
>
>
>
|







242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
      ** if --hash is used, check to see if they have been edited by
      ** looking at their artifact hashes */
      const char *zUuid = db_column_text(&q, 5);
      int nUuid = db_column_bytes(&q, 5);
      assert( origSize==currentSize );
      if( !hname_verify_file_hash(zName, zUuid, nUuid) ) chnged = 1;
    }
    /* Before updating VFILE below, currentMtime may need an update:
    ** 1. If file was modified just now, set to 0 as done when merging.
    **    Next time we check, we will likely check the hash and update mtime.
    ** 2. Set to manifest time, if requested.
    */
    if( currentMtime >= now ){
      currentMtime = 0;
    } else if( (cksigFlags & CKSIG_SETMTIME) && (chnged==0 || chnged==2 || chnged==4)){
      i64 desiredMtime;
      if( mtime_of_manifest_file(vid,rid,&desiredMtime)==0 ){
        if( currentMtime!=desiredMtime ){
          file_set_mtime(zName, desiredMtime);
          currentMtime = file_mtime(zName, RepoFILE);
        }
      }
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    if( file_unsafe_in_tree_path(zName) ){
      continue;
    }
    content_get(rid, &content);
    if( file_is_the_same(&content, zName) ){
      blob_reset(&content);
      if( file_setexe(zName, isExe) ){
        db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
                      file_mtime(zName, RepoFILE), id);
      }
      continue;
    }
    if( promptFlag && file_size(zName, RepoFILE)>=0 ){
      Blob ans;
      char *zMsg;
      char cReply;







|
<







330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
    if( file_unsafe_in_tree_path(zName) ){
      continue;
    }
    content_get(rid, &content);
    if( file_is_the_same(&content, zName) ){
      blob_reset(&content);
      if( file_setexe(zName, isExe) ){
        db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", id);

      }
      continue;
    }
    if( promptFlag && file_size(zName, RepoFILE)>=0 ){
      Blob ans;
      char *zMsg;
      char cReply;
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
    if( isLink ){
      symlink_create(blob_str(&content), zName);
    }else{
      blob_write_to_file(&content, zName);
    }
    file_setexe(zName, isExe);
    blob_reset(&content);
    db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
                  file_mtime(zName, RepoFILE), id);
  }
  db_finalize(&q);
}

/*
** Check to see if the directory named in zPath is the top of a check-out.
** In other words, check to see if directory pPath contains a file named







|
<







365
366
367
368
369
370
371
372

373
374
375
376
377
378
379
    if( isLink ){
      symlink_create(blob_str(&content), zName);
    }else{
      blob_write_to_file(&content, zName);
    }
    file_setexe(zName, isExe);
    blob_reset(&content);
    db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", id);

  }
  db_finalize(&q);
}

/*
** Check to see if the directory named in zPath is the top of a check-out.
** In other words, check to see if directory pPath contains a file named