Fossil SCM

Reworked the "touch" command to be able to handle non-glob filenames.

stephan 2019-06-13 20:12 trunk
Commit 1b49ab3c6c414a2cf76eab1acb0a72dcf9489390048f5148bfa0cb2601c251f8
1 file changed +218 -58
+218 -58
--- src/file.c
+++ src/file.c
@@ -1799,43 +1799,114 @@
17991799
zDir = g.argv[2];
18001800
zGlob = g.argc==4 ? g.argv[3] : 0;
18011801
fossil_print("%d\n", file_directory_size(zDir, zGlob, omitDotFiles));
18021802
}
18031803
1804
+/*
1805
+** Internal helper for touch_cmd(). zAbsName must be resolvable as-is
1806
+** to a file - this function does not expand/normalize it. i.e. it
1807
+** "really should" be an absolute path. zTreeName is strictly
1808
+** cosmetic: it is used when dryRunFlag or verboseFlag generate
1809
+** output. It is assumed to be a repo-relative or or subdir-relative
1810
+** filename.
1811
+**
1812
+** newMTime is the file's new timestamp (Unix epoch).
1813
+**
1814
+** Returns 1 if it sets zAbsName's mtime, 0 if it does not (indicating
1815
+** that the file already has that timestamp). Dies fatally if given an
1816
+** unresolvable filename. If dryRunFlag is true then it outputs the
1817
+** name of the file it would have timestamped but does not stamp the
1818
+** file. If verboseFlag is true, it outputs a message if the files
1819
+** timestamp is actually modified.
1820
+*/
1821
+static int touch_cmd_stamp_one_file(char const *zAbsName,
1822
+ char const *zTreeName,
1823
+ i64 newMtime, int dryRunFlag,
1824
+ int verboseFlag){
1825
+ i64 const currentMtime = file_mtime(zAbsName, 0);
1826
+ if(currentMtime<0){
1827
+ fossil_fatal("Cannot stat file: %s\n", zAbsName);
1828
+ }else if(currentMtime==newMtime){
1829
+ return 0;
1830
+ }else if( dryRunFlag!=0 ){
1831
+ fossil_print( "dry-run: %s\n", zTreeName );
1832
+ }else{
1833
+ file_set_mtime(zAbsName, newMtime);
1834
+ if( verboseFlag!=0 ){
1835
+ fossil_print( "touched %s\n", zTreeName );
1836
+ }
1837
+ }
1838
+ return 1;
1839
+}
1840
+
1841
+/*
1842
+** Internal helper for touch_cmd(). If the given name is found in the
1843
+** given checkout version, which MUST be the checkout version
1844
+** currently populating the vfile table, the vfile.mrid value for the
1845
+** file is returned, else 0 is returned. zName must be resolvable
1846
+** as-is - this function performs neither expands nor normalizes it.
1847
+*/
1848
+static int touch_cmd_vfile_mrid( int vid, char const *zName ){
1849
+ int mrid = 0;
1850
+ static Stmt q = empty_Stmt_m;
1851
+ db_static_prepare(&q, "SELECT vfile.mrid "
1852
+ "FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid "
1853
+ "WHERE vid=:vid AND pathname=:pathname %s",
1854
+ filename_collation());
1855
+ db_bind_int(&q, ":vid", vid);
1856
+ db_bind_text(&q, ":pathname", zName);
1857
+ if(SQLITE_ROW==db_step(&q)){
1858
+ mrid = db_column_int(&q, 0);
1859
+ }
1860
+ db_reset(&q);
1861
+ return mrid;
1862
+}
18041863
18051864
/*
18061865
** COMMAND: touch*
18071866
**
1808
-** Usage: %fossil touch ?OPTIONS?
1867
+** Usage: %fossil touch ?OPTIONS? ?FILENAME...?
18091868
**
18101869
** For each file in the current checkout matching one of the provided
1811
-** list of glob patterns, or all files if no globs are provided, sets
1812
-** the file's mtime to the time of the last checkin which modified
1813
-** that file.
1870
+** list of glob patterns and/or file names, the file's mtime is
1871
+** updated to a value specified by one of the flags --checkout,
1872
+** --checkin, or --now.
1873
+**
1874
+** If neither glob patterns nor filenames are provided, it operates on
1875
+** all files managed by the currently checked-out version.
18141876
**
18151877
** This command gets its name from the conventional Unix "touch"
18161878
** command.
18171879
**
18181880
** Options:
18191881
** --now Stamp each affected file with the current time.
18201882
** This is the default behavior.
18211883
** -c|--checkin Stamp each affected file with the time of the
1822
-** most recent checkin which modified that file.
1884
+** most recent check-in which modified that file.
1885
+** -C|--checkout Stamp each affected file with the time of the
1886
+** currently-checked-out version.
18231887
** -g GLOBLIST Comma-separated list of glob patterns. Default
18241888
** is to touch all SCM-controlled files.
18251889
** -G GLOBFILE Similar to -g but reads its globs from a
18261890
** fossil-conventional glob list file.
1827
-** -v|-verbose Outputs information about its globs and each
1828
-** file it touches.
1891
+** -v|-verbose Outputs extra information about its globs
1892
+** and each file it touches.
18291893
** -n|--dry-run Outputs which files would require touching,
18301894
** but does not touch them.
1895
+** -q|--quiet Suppress warnings when skipping unmanaged
1896
+** or out-of-tree files.
18311897
**
1832
-** Only one of -g or -G may be used. If neither is provided,
1833
-** the effect is as if a glob of '*' were provided.
1898
+** Only one of --now, --checkin, and --checkout may be used. The
1899
+** default is --now.
18341900
**
1835
-** Only one of --now and --checkin may be used. The default
1836
-** is --now.
1901
+** Only one of -g or -G may be used. If neither is provided and no
1902
+** additional filenames are provided, the effect is as if a glob of
1903
+** '*' were provided. Note that all glob patterns provided via these
1904
+** flags are always evaluated as if they are relative to the top of
1905
+** the source tree, not the current working (sub)directory. Filenames
1906
+** provided without these flags, on the other hand, are treated as
1907
+** relative to the current directory.
18371908
**
18381909
*/
18391910
void touch_cmd(){
18401911
const char * zGlobList; /* -g List of glob patterns */
18411912
const char * zGlobFile; /* -G File of glob patterns */
@@ -1842,87 +1913,176 @@
18421913
Glob * pGlob = 0; /* List of glob patterns */
18431914
int verboseFlag;
18441915
int dryRunFlag;
18451916
int vid; /* Checkout version */
18461917
int changeCount = 0; /* Number of files touched */
1847
- int checkinFlag; /* -c|--checkin */
1848
- i64 const nowTime = time(0);
1918
+ int quietFlag = 0; /* -q|--quiet */
1919
+ int timeFlag; /* -1==--checkin, 1==--checkout, 0==--now */
1920
+ i64 nowTime = 0; /* Timestamp of --now or --checkout */
18491921
Stmt q;
1922
+ Blob absBuffer = empty_blob;
18501923
18511924
verboseFlag = find_option("verbose","v",0)!=0;
1852
- dryRunFlag = find_option("dry-run","n",0)!=0;
1925
+ quietFlag = find_option("quiet","q",0)!=0;
1926
+ dryRunFlag = find_option("dry-run","n",0)!=0
1927
+ || find_option("dryrun",0,0)!=0;
18531928
zGlobList = find_option("glob", "g",1);
18541929
zGlobFile = find_option("globfile", "G",1);
1855
- checkinFlag = find_option("checkin","c",0)!=0;
18561930
1857
- if(find_option("now",0,0)!=0 && checkinFlag!=0){
1858
- fossil_fatal("Options --checkin and --now may not be used together.");
1859
- }
18601931
if(zGlobList && zGlobFile){
18611932
fossil_fatal("Options -g and -G may not be used together.");
18621933
}
1934
+
1935
+ {
1936
+ int const ci =
1937
+ (find_option("checkin","c",0) || find_option("check-in",0,0))
1938
+ ? 1 : 0;
1939
+ int const co = find_option("checkout","C",0) ? 1 : 0;
1940
+ int const now = find_option("now",0,0) ? 1 : 0;
1941
+ if(ci + co + now > 1){
1942
+ fossil_fatal("Options --checkin, --checkout, and --now may "
1943
+ "not be used together.");
1944
+ }else if(co){
1945
+ timeFlag = 1;
1946
+ if(verboseFlag){
1947
+ fossil_print("Timestamp = current checkout version.\n");
1948
+ }
1949
+ }else if(ci){
1950
+ timeFlag = -1;
1951
+ if(verboseFlag){
1952
+ fossil_print("Timestamp = checkin in which each file was "
1953
+ "most recently modified.\n");
1954
+ }
1955
+ }else{
1956
+ timeFlag = 0;
1957
+ if(verboseFlag){
1958
+ fossil_print("Timestamp = current system time.\n");
1959
+ }
1960
+ }
1961
+ }
18631962
18641963
verify_all_options();
18651964
18661965
db_must_be_within_tree();
18671966
vid = db_lget_int("checkout", 0);
18681967
if(vid==0){
18691968
fossil_fatal("Cannot determine checkout version.");
18701969
}
1970
+
18711971
if(zGlobList){
18721972
pGlob = *zGlobList ? glob_create(zGlobList) : 0;
18731973
}else if(zGlobFile){
1874
- Blob globs;
1974
+ Blob globs = empty_blob;
18751975
blob_read_from_file(&globs, zGlobFile, ExtFILE);
18761976
pGlob = glob_create( globs.aData );
18771977
blob_reset(&globs);
18781978
}
1879
- db_begin_transaction();
1880
- db_prepare(&q, "SELECT vfile.mrid, pathname "
1881
- "FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid "
1882
- "WHERE vid=%d", vid);
18831979
if( pGlob && verboseFlag!=0 ){
18841980
int i;
18851981
for(i=0; i<pGlob->nPattern; ++i){
18861982
fossil_print("glob: %s\n", pGlob->azPattern[i]);
18871983
}
18881984
}
1889
- if( verboseFlag ){
1890
- if(checkinFlag){
1891
- fossil_print("Using mtime from most recent commit(s).\n");
1892
- }else{
1893
- fossil_print("Using current time.\n");
1894
- }
1895
- }
1896
- while(SQLITE_ROW==db_step(&q)){
1897
- const char * zName = db_column_text(&q, 1);
1898
- int const fid = db_column_int(&q, 0);
1899
- i64 newMtime = checkinFlag ? 0 : nowTime;
1900
- i64 currentMtime;
1901
- if(pGlob){
1902
- if(glob_match(pGlob, zName)==0) continue;
1903
- }
1904
- currentMtime = file_mtime(zName, 0);
1905
- if( newMtime || mtime_of_manifest_file(vid, fid, &newMtime)==0 ){
1906
- if( currentMtime!=newMtime ){
1907
- ++changeCount;
1908
- if( dryRunFlag!=0 ){
1909
- fossil_print( "dry-run: %s\n", zName );
1910
- }else{
1911
- file_set_mtime(zName, newMtime);
1912
- if( verboseFlag!=0 ){
1913
- fossil_print( "touched %s\n", zName );
1914
- }
1915
- }
1916
- }
1917
- }
1918
- }
1919
- db_finalize(&q);
1920
- db_end_transaction(0);
1921
- glob_free(pGlob);
1985
+
1986
+ db_begin_transaction();
1987
+ if(timeFlag==0){/*--now*/
1988
+ nowTime = time(0);
1989
+ }else if(timeFlag>0){/*--checkout: get the checkout
1990
+ manifest's timestamp*/
1991
+ assert(vid>0);
1992
+ nowTime = db_int64(-1,
1993
+ "SELECT CAST(strftime('%%s',"
1994
+ "(SELECT mtime FROM event WHERE objid=%d)"
1995
+ ") AS INTEGER)", vid);
1996
+ if(nowTime<0){
1997
+ fossil_fatal("Could not determine out checkout version's time!");
1998
+ }
1999
+ }else{ /* --checkin */
2000
+ assert(0 == nowTime);
2001
+ }
2002
+ if((pGlob && pGlob->nPattern>0)
2003
+ || g.argc<3 /* no non-flag arguments */ ){
2004
+ /*
2005
+ ** We have either globs or no trailing filenames (in which case an
2006
+ ** effective glob pattern of '*' is assumed). If there are neither
2007
+ ** globs nor filenames then we operate on all managed files.
2008
+ */
2009
+ db_prepare(&q,
2010
+ "SELECT vfile.mrid, pathname "
2011
+ "FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid "
2012
+ "WHERE vid=%d", vid);
2013
+ while(SQLITE_ROW==db_step(&q)){
2014
+ int const fid = db_column_int(&q, 0);
2015
+ const char * zName = db_column_text(&q, 1);
2016
+ i64 newMtime = nowTime;
2017
+ char const * zAbs = 0; /* absolute path */
2018
+ absBuffer.nUsed = 0;
2019
+ assert(timeFlag<0 ? newMtime==0 : newMtime>0);
2020
+ if(pGlob){
2021
+ if(glob_match(pGlob, zName)==0) continue;
2022
+ }
2023
+ blob_appendf( &absBuffer, "%s%s", g.zLocalRoot, zName );
2024
+ zAbs = blob_str(&absBuffer);
2025
+ if( newMtime || mtime_of_manifest_file(vid, fid, &newMtime)==0 ){
2026
+ changeCount +=
2027
+ touch_cmd_stamp_one_file( zAbs, zName, newMtime,
2028
+ dryRunFlag, verboseFlag );
2029
+ }
2030
+ }
2031
+ db_finalize(&q);
2032
+ }
2033
+ glob_free(pGlob);
2034
+ pGlob = 0;
2035
+ if(g.argc>2){
2036
+ /*
2037
+ ** Trailing filenames on the command line. These require extra
2038
+ ** care to avoid modifying unmanaged or out-of-tree files and
2039
+ ** finding an associated --checkin timestamp.
2040
+ */
2041
+ int i;
2042
+ Blob treeNameBuf = empty_blob;
2043
+ for( i = 2; i < g.argc; ++i,
2044
+ blob_reset(&treeNameBuf) ){
2045
+ char const * zArg = g.argv[i];
2046
+ char const * zTreeFile; /* repo-relative filename */
2047
+ char const * zAbs; /* absolute filename */
2048
+ i64 newMtime = nowTime;
2049
+ int nameCheck;
2050
+ int fid; /* vfile.mrid of file */
2051
+ absBuffer.nUsed = 0;
2052
+ nameCheck = file_tree_name( zArg, &treeNameBuf, 0, 0 );
2053
+ if(nameCheck==0){
2054
+ if(quietFlag==0){
2055
+ fossil_print("SKIPPING out-of-tree file: %s\n", zArg);
2056
+ }
2057
+ continue;
2058
+ }
2059
+ zTreeFile = blob_str(&treeNameBuf);
2060
+ fid = touch_cmd_vfile_mrid( vid, zTreeFile );
2061
+ if(fid==0){
2062
+ if(quietFlag==0){
2063
+ fossil_print("SKIPPING unmanaged file: %s\n", zArg);
2064
+ }
2065
+ continue;
2066
+ }
2067
+ blob_appendf(&absBuffer, "%s%s", g.zLocalRoot, zTreeFile);
2068
+ zAbs = blob_str(&absBuffer);
2069
+ if(timeFlag<0){/*--checkin*/
2070
+ if(mtime_of_manifest_file( vid, fid, &newMtime )!=0){
2071
+ fossil_fatal("Could not resolve --checkin mtime of %s", zTreeFile);
2072
+ }
2073
+ }else{
2074
+ assert(newMtime>0);
2075
+ }
2076
+ changeCount +=
2077
+ touch_cmd_stamp_one_file( zAbs, zArg, newMtime,
2078
+ dryRunFlag, verboseFlag );
2079
+ }
2080
+ }
2081
+ db_end_transaction(0);
2082
+ blob_reset(&absBuffer);
19222083
if( dryRunFlag!=0 ){
19232084
fossil_print("dry-run: would have touched %d file(s)\n",
19242085
changeCount);
1925
- }else if( verboseFlag!=0 ){
1926
- fossil_print("Touched %d file(s)\n", changeCount);
19272086
}
2087
+ fossil_print("Touched %d file(s)\n", changeCount);
19282088
}
19292089
--- src/file.c
+++ src/file.c
@@ -1799,43 +1799,114 @@
1799 zDir = g.argv[2];
1800 zGlob = g.argc==4 ? g.argv[3] : 0;
1801 fossil_print("%d\n", file_directory_size(zDir, zGlob, omitDotFiles));
1802 }
1803
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1804
1805 /*
1806 ** COMMAND: touch*
1807 **
1808 ** Usage: %fossil touch ?OPTIONS?
1809 **
1810 ** For each file in the current checkout matching one of the provided
1811 ** list of glob patterns, or all files if no globs are provided, sets
1812 ** the file's mtime to the time of the last checkin which modified
1813 ** that file.
 
 
 
1814 **
1815 ** This command gets its name from the conventional Unix "touch"
1816 ** command.
1817 **
1818 ** Options:
1819 ** --now Stamp each affected file with the current time.
1820 ** This is the default behavior.
1821 ** -c|--checkin Stamp each affected file with the time of the
1822 ** most recent checkin which modified that file.
 
 
1823 ** -g GLOBLIST Comma-separated list of glob patterns. Default
1824 ** is to touch all SCM-controlled files.
1825 ** -G GLOBFILE Similar to -g but reads its globs from a
1826 ** fossil-conventional glob list file.
1827 ** -v|-verbose Outputs information about its globs and each
1828 ** file it touches.
1829 ** -n|--dry-run Outputs which files would require touching,
1830 ** but does not touch them.
 
 
1831 **
1832 ** Only one of -g or -G may be used. If neither is provided,
1833 ** the effect is as if a glob of '*' were provided.
1834 **
1835 ** Only one of --now and --checkin may be used. The default
1836 ** is --now.
 
 
 
 
 
1837 **
1838 */
1839 void touch_cmd(){
1840 const char * zGlobList; /* -g List of glob patterns */
1841 const char * zGlobFile; /* -G File of glob patterns */
@@ -1842,87 +1913,176 @@
1842 Glob * pGlob = 0; /* List of glob patterns */
1843 int verboseFlag;
1844 int dryRunFlag;
1845 int vid; /* Checkout version */
1846 int changeCount = 0; /* Number of files touched */
1847 int checkinFlag; /* -c|--checkin */
1848 i64 const nowTime = time(0);
 
1849 Stmt q;
 
1850
1851 verboseFlag = find_option("verbose","v",0)!=0;
1852 dryRunFlag = find_option("dry-run","n",0)!=0;
 
 
1853 zGlobList = find_option("glob", "g",1);
1854 zGlobFile = find_option("globfile", "G",1);
1855 checkinFlag = find_option("checkin","c",0)!=0;
1856
1857 if(find_option("now",0,0)!=0 && checkinFlag!=0){
1858 fossil_fatal("Options --checkin and --now may not be used together.");
1859 }
1860 if(zGlobList && zGlobFile){
1861 fossil_fatal("Options -g and -G may not be used together.");
1862 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1863
1864 verify_all_options();
1865
1866 db_must_be_within_tree();
1867 vid = db_lget_int("checkout", 0);
1868 if(vid==0){
1869 fossil_fatal("Cannot determine checkout version.");
1870 }
 
1871 if(zGlobList){
1872 pGlob = *zGlobList ? glob_create(zGlobList) : 0;
1873 }else if(zGlobFile){
1874 Blob globs;
1875 blob_read_from_file(&globs, zGlobFile, ExtFILE);
1876 pGlob = glob_create( globs.aData );
1877 blob_reset(&globs);
1878 }
1879 db_begin_transaction();
1880 db_prepare(&q, "SELECT vfile.mrid, pathname "
1881 "FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid "
1882 "WHERE vid=%d", vid);
1883 if( pGlob && verboseFlag!=0 ){
1884 int i;
1885 for(i=0; i<pGlob->nPattern; ++i){
1886 fossil_print("glob: %s\n", pGlob->azPattern[i]);
1887 }
1888 }
1889 if( verboseFlag ){
1890 if(checkinFlag){
1891 fossil_print("Using mtime from most recent commit(s).\n");
1892 }else{
1893 fossil_print("Using current time.\n");
1894 }
1895 }
1896 while(SQLITE_ROW==db_step(&q)){
1897 const char * zName = db_column_text(&q, 1);
1898 int const fid = db_column_int(&q, 0);
1899 i64 newMtime = checkinFlag ? 0 : nowTime;
1900 i64 currentMtime;
1901 if(pGlob){
1902 if(glob_match(pGlob, zName)==0) continue;
1903 }
1904 currentMtime = file_mtime(zName, 0);
1905 if( newMtime || mtime_of_manifest_file(vid, fid, &newMtime)==0 ){
1906 if( currentMtime!=newMtime ){
1907 ++changeCount;
1908 if( dryRunFlag!=0 ){
1909 fossil_print( "dry-run: %s\n", zName );
1910 }else{
1911 file_set_mtime(zName, newMtime);
1912 if( verboseFlag!=0 ){
1913 fossil_print( "touched %s\n", zName );
1914 }
1915 }
1916 }
1917 }
1918 }
1919 db_finalize(&q);
1920 db_end_transaction(0);
1921 glob_free(pGlob);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1922 if( dryRunFlag!=0 ){
1923 fossil_print("dry-run: would have touched %d file(s)\n",
1924 changeCount);
1925 }else if( verboseFlag!=0 ){
1926 fossil_print("Touched %d file(s)\n", changeCount);
1927 }
 
1928 }
1929
--- src/file.c
+++ src/file.c
@@ -1799,43 +1799,114 @@
1799 zDir = g.argv[2];
1800 zGlob = g.argc==4 ? g.argv[3] : 0;
1801 fossil_print("%d\n", file_directory_size(zDir, zGlob, omitDotFiles));
1802 }
1803
1804 /*
1805 ** Internal helper for touch_cmd(). zAbsName must be resolvable as-is
1806 ** to a file - this function does not expand/normalize it. i.e. it
1807 ** "really should" be an absolute path. zTreeName is strictly
1808 ** cosmetic: it is used when dryRunFlag or verboseFlag generate
1809 ** output. It is assumed to be a repo-relative or or subdir-relative
1810 ** filename.
1811 **
1812 ** newMTime is the file's new timestamp (Unix epoch).
1813 **
1814 ** Returns 1 if it sets zAbsName's mtime, 0 if it does not (indicating
1815 ** that the file already has that timestamp). Dies fatally if given an
1816 ** unresolvable filename. If dryRunFlag is true then it outputs the
1817 ** name of the file it would have timestamped but does not stamp the
1818 ** file. If verboseFlag is true, it outputs a message if the files
1819 ** timestamp is actually modified.
1820 */
1821 static int touch_cmd_stamp_one_file(char const *zAbsName,
1822 char const *zTreeName,
1823 i64 newMtime, int dryRunFlag,
1824 int verboseFlag){
1825 i64 const currentMtime = file_mtime(zAbsName, 0);
1826 if(currentMtime<0){
1827 fossil_fatal("Cannot stat file: %s\n", zAbsName);
1828 }else if(currentMtime==newMtime){
1829 return 0;
1830 }else if( dryRunFlag!=0 ){
1831 fossil_print( "dry-run: %s\n", zTreeName );
1832 }else{
1833 file_set_mtime(zAbsName, newMtime);
1834 if( verboseFlag!=0 ){
1835 fossil_print( "touched %s\n", zTreeName );
1836 }
1837 }
1838 return 1;
1839 }
1840
1841 /*
1842 ** Internal helper for touch_cmd(). If the given name is found in the
1843 ** given checkout version, which MUST be the checkout version
1844 ** currently populating the vfile table, the vfile.mrid value for the
1845 ** file is returned, else 0 is returned. zName must be resolvable
1846 ** as-is - this function performs neither expands nor normalizes it.
1847 */
1848 static int touch_cmd_vfile_mrid( int vid, char const *zName ){
1849 int mrid = 0;
1850 static Stmt q = empty_Stmt_m;
1851 db_static_prepare(&q, "SELECT vfile.mrid "
1852 "FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid "
1853 "WHERE vid=:vid AND pathname=:pathname %s",
1854 filename_collation());
1855 db_bind_int(&q, ":vid", vid);
1856 db_bind_text(&q, ":pathname", zName);
1857 if(SQLITE_ROW==db_step(&q)){
1858 mrid = db_column_int(&q, 0);
1859 }
1860 db_reset(&q);
1861 return mrid;
1862 }
1863
1864 /*
1865 ** COMMAND: touch*
1866 **
1867 ** Usage: %fossil touch ?OPTIONS? ?FILENAME...?
1868 **
1869 ** For each file in the current checkout matching one of the provided
1870 ** list of glob patterns and/or file names, the file's mtime is
1871 ** updated to a value specified by one of the flags --checkout,
1872 ** --checkin, or --now.
1873 **
1874 ** If neither glob patterns nor filenames are provided, it operates on
1875 ** all files managed by the currently checked-out version.
1876 **
1877 ** This command gets its name from the conventional Unix "touch"
1878 ** command.
1879 **
1880 ** Options:
1881 ** --now Stamp each affected file with the current time.
1882 ** This is the default behavior.
1883 ** -c|--checkin Stamp each affected file with the time of the
1884 ** most recent check-in which modified that file.
1885 ** -C|--checkout Stamp each affected file with the time of the
1886 ** currently-checked-out version.
1887 ** -g GLOBLIST Comma-separated list of glob patterns. Default
1888 ** is to touch all SCM-controlled files.
1889 ** -G GLOBFILE Similar to -g but reads its globs from a
1890 ** fossil-conventional glob list file.
1891 ** -v|-verbose Outputs extra information about its globs
1892 ** and each file it touches.
1893 ** -n|--dry-run Outputs which files would require touching,
1894 ** but does not touch them.
1895 ** -q|--quiet Suppress warnings when skipping unmanaged
1896 ** or out-of-tree files.
1897 **
1898 ** Only one of --now, --checkin, and --checkout may be used. The
1899 ** default is --now.
1900 **
1901 ** Only one of -g or -G may be used. If neither is provided and no
1902 ** additional filenames are provided, the effect is as if a glob of
1903 ** '*' were provided. Note that all glob patterns provided via these
1904 ** flags are always evaluated as if they are relative to the top of
1905 ** the source tree, not the current working (sub)directory. Filenames
1906 ** provided without these flags, on the other hand, are treated as
1907 ** relative to the current directory.
1908 **
1909 */
1910 void touch_cmd(){
1911 const char * zGlobList; /* -g List of glob patterns */
1912 const char * zGlobFile; /* -G File of glob patterns */
@@ -1842,87 +1913,176 @@
1913 Glob * pGlob = 0; /* List of glob patterns */
1914 int verboseFlag;
1915 int dryRunFlag;
1916 int vid; /* Checkout version */
1917 int changeCount = 0; /* Number of files touched */
1918 int quietFlag = 0; /* -q|--quiet */
1919 int timeFlag; /* -1==--checkin, 1==--checkout, 0==--now */
1920 i64 nowTime = 0; /* Timestamp of --now or --checkout */
1921 Stmt q;
1922 Blob absBuffer = empty_blob;
1923
1924 verboseFlag = find_option("verbose","v",0)!=0;
1925 quietFlag = find_option("quiet","q",0)!=0;
1926 dryRunFlag = find_option("dry-run","n",0)!=0
1927 || find_option("dryrun",0,0)!=0;
1928 zGlobList = find_option("glob", "g",1);
1929 zGlobFile = find_option("globfile", "G",1);
 
1930
 
 
 
1931 if(zGlobList && zGlobFile){
1932 fossil_fatal("Options -g and -G may not be used together.");
1933 }
1934
1935 {
1936 int const ci =
1937 (find_option("checkin","c",0) || find_option("check-in",0,0))
1938 ? 1 : 0;
1939 int const co = find_option("checkout","C",0) ? 1 : 0;
1940 int const now = find_option("now",0,0) ? 1 : 0;
1941 if(ci + co + now > 1){
1942 fossil_fatal("Options --checkin, --checkout, and --now may "
1943 "not be used together.");
1944 }else if(co){
1945 timeFlag = 1;
1946 if(verboseFlag){
1947 fossil_print("Timestamp = current checkout version.\n");
1948 }
1949 }else if(ci){
1950 timeFlag = -1;
1951 if(verboseFlag){
1952 fossil_print("Timestamp = checkin in which each file was "
1953 "most recently modified.\n");
1954 }
1955 }else{
1956 timeFlag = 0;
1957 if(verboseFlag){
1958 fossil_print("Timestamp = current system time.\n");
1959 }
1960 }
1961 }
1962
1963 verify_all_options();
1964
1965 db_must_be_within_tree();
1966 vid = db_lget_int("checkout", 0);
1967 if(vid==0){
1968 fossil_fatal("Cannot determine checkout version.");
1969 }
1970
1971 if(zGlobList){
1972 pGlob = *zGlobList ? glob_create(zGlobList) : 0;
1973 }else if(zGlobFile){
1974 Blob globs = empty_blob;
1975 blob_read_from_file(&globs, zGlobFile, ExtFILE);
1976 pGlob = glob_create( globs.aData );
1977 blob_reset(&globs);
1978 }
 
 
 
 
1979 if( pGlob && verboseFlag!=0 ){
1980 int i;
1981 for(i=0; i<pGlob->nPattern; ++i){
1982 fossil_print("glob: %s\n", pGlob->azPattern[i]);
1983 }
1984 }
1985
1986 db_begin_transaction();
1987 if(timeFlag==0){/*--now*/
1988 nowTime = time(0);
1989 }else if(timeFlag>0){/*--checkout: get the checkout
1990 manifest's timestamp*/
1991 assert(vid>0);
1992 nowTime = db_int64(-1,
1993 "SELECT CAST(strftime('%%s',"
1994 "(SELECT mtime FROM event WHERE objid=%d)"
1995 ") AS INTEGER)", vid);
1996 if(nowTime<0){
1997 fossil_fatal("Could not determine out checkout version's time!");
1998 }
1999 }else{ /* --checkin */
2000 assert(0 == nowTime);
2001 }
2002 if((pGlob && pGlob->nPattern>0)
2003 || g.argc<3 /* no non-flag arguments */ ){
2004 /*
2005 ** We have either globs or no trailing filenames (in which case an
2006 ** effective glob pattern of '*' is assumed). If there are neither
2007 ** globs nor filenames then we operate on all managed files.
2008 */
2009 db_prepare(&q,
2010 "SELECT vfile.mrid, pathname "
2011 "FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid "
2012 "WHERE vid=%d", vid);
2013 while(SQLITE_ROW==db_step(&q)){
2014 int const fid = db_column_int(&q, 0);
2015 const char * zName = db_column_text(&q, 1);
2016 i64 newMtime = nowTime;
2017 char const * zAbs = 0; /* absolute path */
2018 absBuffer.nUsed = 0;
2019 assert(timeFlag<0 ? newMtime==0 : newMtime>0);
2020 if(pGlob){
2021 if(glob_match(pGlob, zName)==0) continue;
2022 }
2023 blob_appendf( &absBuffer, "%s%s", g.zLocalRoot, zName );
2024 zAbs = blob_str(&absBuffer);
2025 if( newMtime || mtime_of_manifest_file(vid, fid, &newMtime)==0 ){
2026 changeCount +=
2027 touch_cmd_stamp_one_file( zAbs, zName, newMtime,
2028 dryRunFlag, verboseFlag );
2029 }
2030 }
2031 db_finalize(&q);
2032 }
2033 glob_free(pGlob);
2034 pGlob = 0;
2035 if(g.argc>2){
2036 /*
2037 ** Trailing filenames on the command line. These require extra
2038 ** care to avoid modifying unmanaged or out-of-tree files and
2039 ** finding an associated --checkin timestamp.
2040 */
2041 int i;
2042 Blob treeNameBuf = empty_blob;
2043 for( i = 2; i < g.argc; ++i,
2044 blob_reset(&treeNameBuf) ){
2045 char const * zArg = g.argv[i];
2046 char const * zTreeFile; /* repo-relative filename */
2047 char const * zAbs; /* absolute filename */
2048 i64 newMtime = nowTime;
2049 int nameCheck;
2050 int fid; /* vfile.mrid of file */
2051 absBuffer.nUsed = 0;
2052 nameCheck = file_tree_name( zArg, &treeNameBuf, 0, 0 );
2053 if(nameCheck==0){
2054 if(quietFlag==0){
2055 fossil_print("SKIPPING out-of-tree file: %s\n", zArg);
2056 }
2057 continue;
2058 }
2059 zTreeFile = blob_str(&treeNameBuf);
2060 fid = touch_cmd_vfile_mrid( vid, zTreeFile );
2061 if(fid==0){
2062 if(quietFlag==0){
2063 fossil_print("SKIPPING unmanaged file: %s\n", zArg);
2064 }
2065 continue;
2066 }
2067 blob_appendf(&absBuffer, "%s%s", g.zLocalRoot, zTreeFile);
2068 zAbs = blob_str(&absBuffer);
2069 if(timeFlag<0){/*--checkin*/
2070 if(mtime_of_manifest_file( vid, fid, &newMtime )!=0){
2071 fossil_fatal("Could not resolve --checkin mtime of %s", zTreeFile);
2072 }
2073 }else{
2074 assert(newMtime>0);
2075 }
2076 changeCount +=
2077 touch_cmd_stamp_one_file( zAbs, zArg, newMtime,
2078 dryRunFlag, verboseFlag );
2079 }
2080 }
2081 db_end_transaction(0);
2082 blob_reset(&absBuffer);
2083 if( dryRunFlag!=0 ){
2084 fossil_print("dry-run: would have touched %d file(s)\n",
2085 changeCount);
 
 
2086 }
2087 fossil_print("Touched %d file(s)\n", changeCount);
2088 }
2089

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button