Fossil

Check-in [106de276ee]
Login

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

Overview
Comment:Improvements to the logic in the "fossil all" command that removes redundant entries for repositories in the global_config table. If two or more entries share the same inode, only use the first one. On Windows (which lacks inodes) determine uniqueness by the full, canonical pathname.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 106de276eec32eabb265d2b0f40bed48cb58ce6c7b6d6acb5f2f7f7d4327c603
User & Date: drh 2024-11-23 21:27:00.391
References
2024-11-26
05:17
Fix a crash if the test-file-environment command is called from outside a check-out (introduced with [106de276ee]). check-in: 38930fbabe user: florian tags: trunk
Context
2024-11-26
05:17
Fix a crash if the test-file-environment command is called from outside a check-out (introduced with [106de276ee]). check-in: 38930fbabe user: florian tags: trunk
2024-11-24
03:38
Improve situational awareness with "fossil update" by including a message in the changes: information if the name of the branch changes. See [forum:7f5ae505e4144a0c | forum discussion 7f5ae505e4144a0c] for details. check-in: bb9150c403 user: andybradford tags: show-branch-change
2024-11-23
21:27
Improvements to the logic in the "fossil all" command that removes redundant entries for repositories in the global_config table. If two or more entries share the same inode, only use the first one. On Windows (which lacks inodes) determine uniqueness by the full, canonical pathname. check-in: 106de276ee user: drh tags: trunk
17:22
Bug fix for allowing SSH command to be overridden once for sync operations. check-in: 4c6e394d1e user: andybradford tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/allrepo.c.
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
static void collect_argv(Blob *pExtra, int iStart){
  int i;
  for(i=iStart; i<g.argc; i++){
    blob_appendf(pExtra, " %s", g.argv[i]);
  }
}


/*
** COMMAND: all
**
** Usage: %fossil all SUBCOMMAND ...
**
** The ~/.fossil file records the location of all repositories for a
** user.  This command performs certain operations on all repositories







<







48
49
50
51
52
53
54

55
56
57
58
59
60
61
static void collect_argv(Blob *pExtra, int iStart){
  int i;
  for(i=iStart; i<g.argc; i++){
    blob_appendf(pExtra, " %s", g.argv[i]);
  }
}


/*
** COMMAND: all
**
** Usage: %fossil all SUBCOMMAND ...
**
** The ~/.fossil file records the location of all repositories for a
** user.  This command performs certain operations on all repositories
427
428
429
430
431
432
433

434















435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456

457
458
459
460
461
462

463
464
465
466
467

468
469
470
471
472
473
474
  }else{
    fossil_fatal("\"all\" subcommand should be one of: "
      "add cache changes clean dbstat extras fts-config git ignore "
      "info list ls pull push rebuild remote "
      "server settings sync ui unset whatis");
  }
  verify_all_options();

  db_multi_exec("CREATE TEMP TABLE repolist(name,tag);");















  if( useCheckouts ){
    db_multi_exec(
       "INSERT INTO repolist "
       "SELECT DISTINCT substr(name, 7), name COLLATE nocase"
       "  FROM global_config"
       " WHERE substr(name, 1, 6)=='ckout:'"
       " ORDER BY 1"
    );
  }else{
    db_multi_exec(
       "INSERT INTO repolist "
       "SELECT DISTINCT substr(name, 6), name COLLATE nocase"
       "  FROM global_config"
       " WHERE substr(name, 1, 5)=='repo:'"
       " ORDER BY 1"
    );
  }
  db_multi_exec("CREATE TEMP TABLE toDel(x TEXT)");
  db_prepare(&q, "SELECT name, tag FROM repolist ORDER BY 1");
  while( db_step(&q)==SQLITE_ROW ){
    int rc;
    const char *zFilename = db_column_text(&q, 0);

#if !USE_SEE
    if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
#endif
    if( file_access(zFilename, F_OK)
     || !file_is_canonical(zFilename)
     || (useCheckouts && file_isdir(zFilename, ExtFILE)!=1)

    ){
      db_multi_exec("INSERT INTO toDel VALUES(%Q)", db_column_text(&q, 1));
      nToDel++;
      continue;
    }

    if( zCmd[0]=='l' ){
      fossil_print("%s\n", zFilename);
      continue;
    }else if( showFile ){
      fossil_print("%s: %s\n", useCheckouts ? "check-out" : "repository",
                   zFilename);
    }







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|







|





<
|



>






>





>







426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
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
480
481
482
483
484
485
486
487
488
489
490
491
  }else{
    fossil_fatal("\"all\" subcommand should be one of: "
      "add cache changes clean dbstat extras fts-config git ignore "
      "info list ls pull push rebuild remote "
      "server settings sync ui unset whatis");
  }
  verify_all_options();
  db_multi_exec(
     "CREATE TEMP TABLE repolist(\n"
     "  name TEXT, -- Filename\n"
     "  tag TEXT,  -- Key for the GLOBAL_CONFIG table entry\n"
     "  inode TEXT -- Unique identifier for this file\n"
     ");\n"

     /* The seenFile() table holds inode names for entries that have
     ** already been processed.  */
     "CREATE TEMP TABLE seenFile(x TEXT COLLATE nocase);\n"

     /* The toDel() table holds the "tag" for entries that need to be
     ** deleted because they are redundant or no longer exist */
     "CREATE TEMP TABLE toDel(x TEXT);\n"
  );
  sqlite3_create_function(g.db, "inode", 1, SQLITE_UTF8, 0,
                          file_inode_sql_func, 0, 0);
  if( useCheckouts ){
    db_multi_exec(
       "INSERT INTO repolist "
       "SELECT substr(name, 7), name, inode(substr(name,7))"
       "  FROM global_config"
       " WHERE substr(name, 1, 6)=='ckout:'"
       " ORDER BY 1"
    );
  }else{
    db_multi_exec(
       "INSERT INTO repolist "
       "SELECT substr(name, 6), name, inode(substr(name,6))"
       "  FROM global_config"
       " WHERE substr(name, 1, 5)=='repo:'"
       " ORDER BY 1"
    );
  }

  db_prepare(&q,"SELECT name, tag, inode FROM repolist ORDER BY 1");
  while( db_step(&q)==SQLITE_ROW ){
    int rc;
    const char *zFilename = db_column_text(&q, 0);
    const char *zInode = db_column_text(&q,2);
#if !USE_SEE
    if( sqlite3_strglob("*.efossil", zFilename)==0 ) continue;
#endif
    if( file_access(zFilename, F_OK)
     || !file_is_canonical(zFilename)
     || (useCheckouts && file_isdir(zFilename, ExtFILE)!=1)
     || db_exists("SELECT 1 FROM temp.seenFile where x=%Q", zInode)
    ){
      db_multi_exec("INSERT INTO toDel VALUES(%Q)", db_column_text(&q, 1));
      nToDel++;
      continue;
    }
    db_multi_exec("INSERT INTO seenFile(x) VALUES(%Q)", zInode);
    if( zCmd[0]=='l' ){
      fossil_print("%s\n", zFilename);
      continue;
    }else if( showFile ){
      fossil_print("%s: %s\n", useCheckouts ? "check-out" : "repository",
                   zFilename);
    }
Changes to src/db.c.
1555
1556
1557
1558
1559
1560
1561


1562
1563
1564
1565
1566
1567
1568
  sqlite3_create_function(db, "win_reserved", 1, SQLITE_UTF8, 0,
                          db_win_reserved_func,0,0);
  sqlite3_create_function(db, "url_nouser", 1, SQLITE_UTF8, 0,
                          url_nouser_func,0,0);
  sqlite3_create_function(db, "chat_msg_from_event", 4,
        SQLITE_UTF8 | SQLITE_INNOCUOUS, 0,
        chat_msg_from_event, 0, 0);



}

#if USE_SEE
/*
** This is a pointer to the saved database encryption key string.
*/







>
>







1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
  sqlite3_create_function(db, "win_reserved", 1, SQLITE_UTF8, 0,
                          db_win_reserved_func,0,0);
  sqlite3_create_function(db, "url_nouser", 1, SQLITE_UTF8, 0,
                          url_nouser_func,0,0);
  sqlite3_create_function(db, "chat_msg_from_event", 4,
        SQLITE_UTF8 | SQLITE_INNOCUOUS, 0,
        chat_msg_from_event, 0, 0);
  sqlite3_create_function(db, "inode", 1, SQLITE_UTF8, 0,
                          file_inode_sql_func,0,0);

}

#if USE_SEE
/*
** This is a pointer to the saved database encryption key string.
*/
Changes to src/file.c.
1654
1655
1656
1657
1658
1659
1660


1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673



1674
1675
1676
1677
1678
1679
1680
               filenames_are_case_sensitive());
  if( zAllow ){
    g.allowSymlinks = !is_false(zAllow);
  }
  if( zRoot==0 ) zRoot = g.zLocalRoot==0 ? "" : g.zLocalRoot;
  fossil_print("db_allow_symlinks() = %d\n", db_allow_symlinks());
  fossil_print("local-root = [%s]\n", zRoot);


  for(i=2; i<g.argc; i++){
    char *z;
    emitFileStat(g.argv[i], slashFlag, resetFlag);
    z = file_canonical_name_dup(g.argv[i]);
    fossil_print("  file_canonical_name    = %s\n", z);
    fossil_print("  file_nondir_path       = ");
    if( fossil_strnicmp(zRoot,z,(int)strlen(zRoot))!=0 ){
      fossil_print("(--root is not a prefix of this file)\n");
    }else{
      int n = file_nondir_objects_on_path(zRoot, z);
      fossil_print("%.*s\n", n, z);
    }
    fossil_free(z);



  }
}

/*
** COMMAND: test-canonical-name
**
** Usage: %fossil test-canonical-name FILENAME...







>
>













>
>
>







1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
               filenames_are_case_sensitive());
  if( zAllow ){
    g.allowSymlinks = !is_false(zAllow);
  }
  if( zRoot==0 ) zRoot = g.zLocalRoot==0 ? "" : g.zLocalRoot;
  fossil_print("db_allow_symlinks() = %d\n", db_allow_symlinks());
  fossil_print("local-root = [%s]\n", zRoot);
  sqlite3_create_function(g.db, "inode", 1, SQLITE_UTF8, 0,
                          file_inode_sql_func, 0, 0);
  for(i=2; i<g.argc; i++){
    char *z;
    emitFileStat(g.argv[i], slashFlag, resetFlag);
    z = file_canonical_name_dup(g.argv[i]);
    fossil_print("  file_canonical_name    = %s\n", z);
    fossil_print("  file_nondir_path       = ");
    if( fossil_strnicmp(zRoot,z,(int)strlen(zRoot))!=0 ){
      fossil_print("(--root is not a prefix of this file)\n");
    }else{
      int n = file_nondir_objects_on_path(zRoot, z);
      fossil_print("%.*s\n", n, z);
    }
    fossil_free(z);
    z = db_text(0, "SELECT inode(%Q)", g.argv[i]);
    fossil_print("  file_inode_sql_func    = \"%s\"\n", z);
    fossil_free(z);
  }
}

/*
** COMMAND: test-canonical-name
**
** Usage: %fossil test-canonical-name FILENAME...
2978
2979
2980
2981
2982
2983
2984

























































    if(file_isfile(zCkoutDb, ExtFILE)){
      rc = 2;
    }
  }
  fossil_free(zCkoutDb);
  return rc;
}
































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
    if(file_isfile(zCkoutDb, ExtFILE)){
      rc = 2;
    }
  }
  fossil_free(zCkoutDb);
  return rc;
}

/*
** This is the implementation of inode(FILENAME) SQL function.
**
** dev_inode(FILENAME) returns a string.  If FILENAME exists and is
** a regular file, then the return string is of the form:
**
**       DEV/INODE
**
** Where DEV and INODE are the device number and inode number for
** the file.  Or, on Windows, the return value is the canonical
** name of the file, because Windows does not have INODEs.
**
** If FILENAME does not exist, then the return is an empty string.
**
** The value of inode() can be used to eliminate files from a list
** that have duplicates because they have differing names due to links.
**
** Code that wants to use this SQL function needs to first register
** it using a call such as the following:
**
**    sqlite3_create_function(g.db, "inode", 1, SQLITE_UTF8, 0,
**                            file_inode_sql_func, 0, 0);
*/
void file_inode_sql_func(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const char *zFilename;
  assert( argc==1 );
  zFilename = (const char*)sqlite3_value_text(argv[0]);
  if( zFilename==0 || zFilename[0]==0 || file_access(zFilename,F_OK) ){
    sqlite3_result_text(context, "", 0, SQLITE_STATIC);
    return;
  }
#if defined(_WIN32)
  {
    const char *zCanonical = file_canonical_name_dup(zFilename);
    sqlite3_result_text(context, zCanonical, -1, fossil_free);
  }
#else
  {
    struct stat buf;
    int rc;
    memset(&buf, 0, sizeof(buf));
    rc = stat(zFilename, &buf);
    if( rc ){
      sqlite3_result_text(context, "", 0, SQLITE_STATIC);
    }else{
      sqlite3_result_text(context,
         mprintf("%lld/%lld", (i64)buf.st_dev, (i64)buf.st_ino), -1,
         fossil_free);
    }
  }
#endif
}