Fossil SCM
Part 1 of ticket [980a72dedd]: efficient check for determining whether a filename ends with a checkout db name.
Commit
ddd1273ea2358dd9882bb296346f63a2ad55ccccda798928ac9eb25e54a39f1a
Parent
c840617b8b765da…
1 file changed
+55
M
src/db.c
+55
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -1704,10 +1704,65 @@ | ||
| 1704 | 1704 | ** a PRIMARY KEY that includes the new mhash column. However, we must have |
| 1705 | 1705 | ** the repository database at hand in order to do the migration, so that |
| 1706 | 1706 | ** step is deferred. */ |
| 1707 | 1707 | return 1; |
| 1708 | 1708 | } |
| 1709 | + | |
| 1710 | +/* | |
| 1711 | +** Returns true if the given filename ends with any of fossil's | |
| 1712 | +** checkout database filenames: _FOSSIL_ or .fslckout. Specifically, | |
| 1713 | +** it returns 1 if it's an exact match and 2 if it's the tail match | |
| 1714 | +** on a longer input. | |
| 1715 | +** | |
| 1716 | +** zFilename must, for efficiency's sake, be a | |
| 1717 | +** canonicalized/normalized name, e.g. using only '/' as directory | |
| 1718 | +** separators. | |
| 1719 | +** | |
| 1720 | +** nFilename must be the strlen of zFilename. If it is negative, | |
| 1721 | +** strlen() is used to calculate it. | |
| 1722 | +*/ | |
| 1723 | +int is_fossil_ckout_db_name(const char *zFilename, int nFilename){ | |
| 1724 | + const char *zEnd; | |
| 1725 | + | |
| 1726 | + if(nFilename>=0 && nFilename<8/*strlen _FOSSIL_*/) return 0; | |
| 1727 | + else if(nFilename<0) nFilename = (int)strlen(zFilename); | |
| 1728 | + if(nFilename<8) return 0; | |
| 1729 | + zEnd = zFilename + nFilename; | |
| 1730 | + switch(zEnd[-1]){ | |
| 1731 | + case '_': | |
| 1732 | + return fossil_strcmp("_FOSSIL_", &zEnd[-8]) | |
| 1733 | + ? 0 : (8==nFilename ? 1 : ('/'==zEnd[-9] ? 2 : 0)); | |
| 1734 | + case 't': | |
| 1735 | + return (nFilename<9 | |
| 1736 | + || '.'!=zEnd[-9] | |
| 1737 | + || fossil_strcmp(".fslckout", &zEnd[-9])) | |
| 1738 | + ? 0 : (9==nFilename ? 1 : ('/'==zEnd[-10] ? 2 : 0)); | |
| 1739 | + default: | |
| 1740 | + return 0; | |
| 1741 | + } | |
| 1742 | +} | |
| 1743 | + | |
| 1744 | +/* | |
| 1745 | +** COMMAND: test-is-ckout-db | |
| 1746 | +** | |
| 1747 | +** Usage: %fossil test-is-ckout-db FILENAMES... | |
| 1748 | +** | |
| 1749 | +** Passes each given name to is_fossil_ckout_db_name() and outputs one | |
| 1750 | +** line per file: the result value of that function followed by the | |
| 1751 | +** name. | |
| 1752 | +*/ | |
| 1753 | +void test_is_ckout_name_cmd(void){ | |
| 1754 | + int i; | |
| 1755 | + | |
| 1756 | + if(g.argc<3){ | |
| 1757 | + usage("FILENAME_1 [...FILENAME_N]"); | |
| 1758 | + } | |
| 1759 | + for( i = 2; i < g.argc; ++i ){ | |
| 1760 | + const int check = is_fossil_ckout_db_name(g.argv[i], -1); | |
| 1761 | + fossil_print("%d %s\n", check, g.argv[i]); | |
| 1762 | + } | |
| 1763 | +} | |
| 1709 | 1764 | |
| 1710 | 1765 | /* |
| 1711 | 1766 | ** Locate the root directory of the local repository tree. The root |
| 1712 | 1767 | ** directory is found by searching for a file named "_FOSSIL_" or ".fslckout" |
| 1713 | 1768 | ** that contains a valid repository database. |
| 1714 | 1769 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1704,10 +1704,65 @@ | |
| 1704 | ** a PRIMARY KEY that includes the new mhash column. However, we must have |
| 1705 | ** the repository database at hand in order to do the migration, so that |
| 1706 | ** step is deferred. */ |
| 1707 | return 1; |
| 1708 | } |
| 1709 | |
| 1710 | /* |
| 1711 | ** Locate the root directory of the local repository tree. The root |
| 1712 | ** directory is found by searching for a file named "_FOSSIL_" or ".fslckout" |
| 1713 | ** that contains a valid repository database. |
| 1714 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -1704,10 +1704,65 @@ | |
| 1704 | ** a PRIMARY KEY that includes the new mhash column. However, we must have |
| 1705 | ** the repository database at hand in order to do the migration, so that |
| 1706 | ** step is deferred. */ |
| 1707 | return 1; |
| 1708 | } |
| 1709 | |
| 1710 | /* |
| 1711 | ** Returns true if the given filename ends with any of fossil's |
| 1712 | ** checkout database filenames: _FOSSIL_ or .fslckout. Specifically, |
| 1713 | ** it returns 1 if it's an exact match and 2 if it's the tail match |
| 1714 | ** on a longer input. |
| 1715 | ** |
| 1716 | ** zFilename must, for efficiency's sake, be a |
| 1717 | ** canonicalized/normalized name, e.g. using only '/' as directory |
| 1718 | ** separators. |
| 1719 | ** |
| 1720 | ** nFilename must be the strlen of zFilename. If it is negative, |
| 1721 | ** strlen() is used to calculate it. |
| 1722 | */ |
| 1723 | int is_fossil_ckout_db_name(const char *zFilename, int nFilename){ |
| 1724 | const char *zEnd; |
| 1725 | |
| 1726 | if(nFilename>=0 && nFilename<8/*strlen _FOSSIL_*/) return 0; |
| 1727 | else if(nFilename<0) nFilename = (int)strlen(zFilename); |
| 1728 | if(nFilename<8) return 0; |
| 1729 | zEnd = zFilename + nFilename; |
| 1730 | switch(zEnd[-1]){ |
| 1731 | case '_': |
| 1732 | return fossil_strcmp("_FOSSIL_", &zEnd[-8]) |
| 1733 | ? 0 : (8==nFilename ? 1 : ('/'==zEnd[-9] ? 2 : 0)); |
| 1734 | case 't': |
| 1735 | return (nFilename<9 |
| 1736 | || '.'!=zEnd[-9] |
| 1737 | || fossil_strcmp(".fslckout", &zEnd[-9])) |
| 1738 | ? 0 : (9==nFilename ? 1 : ('/'==zEnd[-10] ? 2 : 0)); |
| 1739 | default: |
| 1740 | return 0; |
| 1741 | } |
| 1742 | } |
| 1743 | |
| 1744 | /* |
| 1745 | ** COMMAND: test-is-ckout-db |
| 1746 | ** |
| 1747 | ** Usage: %fossil test-is-ckout-db FILENAMES... |
| 1748 | ** |
| 1749 | ** Passes each given name to is_fossil_ckout_db_name() and outputs one |
| 1750 | ** line per file: the result value of that function followed by the |
| 1751 | ** name. |
| 1752 | */ |
| 1753 | void test_is_ckout_name_cmd(void){ |
| 1754 | int i; |
| 1755 | |
| 1756 | if(g.argc<3){ |
| 1757 | usage("FILENAME_1 [...FILENAME_N]"); |
| 1758 | } |
| 1759 | for( i = 2; i < g.argc; ++i ){ |
| 1760 | const int check = is_fossil_ckout_db_name(g.argv[i], -1); |
| 1761 | fossil_print("%d %s\n", check, g.argv[i]); |
| 1762 | } |
| 1763 | } |
| 1764 | |
| 1765 | /* |
| 1766 | ** Locate the root directory of the local repository tree. The root |
| 1767 | ** directory is found by searching for a file named "_FOSSIL_" or ".fslckout" |
| 1768 | ** that contains a valid repository database. |
| 1769 |