Index: src/db.c ================================================================== --- src/db.c +++ src/db.c @@ -2843,11 +2843,11 @@ ** differ only in case are the same file. Defaults to ** TRUE for unix and FALSE for Cygwin, Mac and Windows. */ #endif /* -** STTING: clean-glob width=40 versionable block-text +** SETTING: clean-glob width=40 versionable block-text ** The VALUE of this setting is a comma or newline-separated list of GLOB ** patterns specifying files that the "clean" command will ** delete without prompting or allowing undo. ** Example: *.a,*.lib,*.o */ @@ -2957,11 +2957,11 @@ */ /* ** SETTING: ignore-glob width=40 versionable block-text ** The value is a comma or newline-separated list of GLOB ** patterns specifying files that the "add", "addremove", -** "clean", and "extra" commands will ignore. +** "clean", and "extras" commands will ignore. ** ** Example: *.log customCode.c notes.txt */ /* ** SETTING: keep-glob width=40 versionable block-text Index: src/diff.c ================================================================== --- src/diff.c +++ src/diff.c @@ -43,13 +43,10 @@ #define DIFF_CONTEXT_EX (((u64)0x04)<<32) /* Use context even if zero */ #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ #define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */ #define DIFF_SLOW_SBS (((u64)0x20)<<32) /* Better, but slower side-by-side */ -/* Annotation flags (any DIFF flag can be used as Annotation flag as well) */ -#define ANN_FILE_VERS (((u64)0x40)<<32) /* File vers not commit vers */ - /* ** These error messages are shared in multiple locations. They are defined ** here for consistency. */ #define DIFF_CANNOT_COMPUTE_BINARY \ @@ -2181,86 +2178,91 @@ return 0; } /* -** Compute a complete annotation on a file. The file is identified -** by its filename number (filename.fnid) and check-in (mlink.mid). +** Compute a complete annotation on a file. The file is identified by its +** filename and check-in name (NULL for current check-in). */ static void annotate_file( Annotator *p, /* The annotator */ - int fnid, /* The name of the file to be annotated */ - int mid, /* Use the version of the file in this check-in */ + const char *zFilename,/* The name of the file to be annotated */ + const char *zRevision,/* Use the version of the file in this check-in */ int iLimit, /* Limit the number of levels if greater than zero */ u64 annFlags /* Flags to alter the annotation */ ){ Blob toAnnotate; /* Text of the final (mid) version of the file */ Blob step; /* Text of previous revision */ - int rid; /* Artifact ID of the file being annotated */ - Stmt q; /* Query returning all ancestor versions */ - Stmt ins; /* Inserts into the temporary VSEEN table */ - int cnt = 0; /* Number of versions examined */ - - /* Initialize the annotation */ - rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid); - if( rid==0 ){ - fossil_fatal("file #%d is unchanged in manifest #%d", fnid, mid); - } - if( !content_get(rid, &toAnnotate) ){ - fossil_fatal("unable to retrieve content of artifact #%d", rid); - } - if( iLimit<=0 ) iLimit = 1000000000; - blob_to_utf8_no_bom(&toAnnotate, 0); - annotation_start(p, &toAnnotate, annFlags); - db_begin_transaction(); - db_multi_exec( - "CREATE TEMP TABLE IF NOT EXISTS vseen(rid INTEGER PRIMARY KEY);" - "DELETE FROM vseen;" - ); - - db_prepare(&ins, "INSERT OR IGNORE INTO vseen(rid) VALUES(:rid)"); - db_prepare(&q, - "SELECT (SELECT uuid FROM blob WHERE rid=mlink.fid)," - " (SELECT uuid FROM blob WHERE rid=mlink.mid)," - " date(event.mtime)," - " coalesce(event.euser,event.user)," - " mlink.pid" - " FROM mlink, event, ancestor" - " WHERE mlink.fid=:rid" - " AND event.objid=mlink.mid" - " AND mlink.pid NOT IN vseen" - " AND ancestor.rid=mlink.mid" - " ORDER BY ancestor.generation;" - ); - - db_bind_int(&q, ":rid", rid); - if( iLimit==0 ) iLimit = 1000000000; - while( rid && iLimit>cnt && db_step(&q)==SQLITE_ROW ){ - int prevId = db_column_int(&q, 4); + Blob treename; /* FILENAME translated to canonical form */ + int cid; /* Selected check-in ID */ + int rid; /* Artifact ID of the file being annotated */ + int fnid; /* Filename ID */ + Stmt q; /* Query returning all ancestor versions */ + int cnt = 0; /* Number of versions analyzed */ + + if( iLimit<=0 ) iLimit = 1000000000; /* A negative limit means no limit */ + db_begin_transaction(); + + /* Get the artificate ID for the check-in begin analyzed */ + if( zRevision ){ + cid = name_to_typed_rid(zRevision, "ci"); + }else{ + db_must_be_within_tree(); + cid = db_lget_int("checkout", 0); + } + + /* Compute all direct ancestors of the check-in being analyzed into + ** the "ancestor" table. */ + compute_direct_ancestors(cid); + + /* Get filename ID */ + file_tree_name(zFilename, &treename, 0, 1); + zFilename = blob_str(&treename); + fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); + + db_prepare(&q, + "SELECT" + " (SELECT uuid FROM blob WHERE rid=mlink.fid)," + " (SELECT uuid FROM blob WHERE rid=mlink.mid)," + " date(event.mtime)," + " coalesce(event.euser,event.user)," + " mlink.fid" + " FROM mlink, event, ancestor" + " WHERE mlink.fnid=%d" + " AND ancestor.rid=mlink.mid" + " AND event.objid=mlink.mid" + " AND mlink.mid!=mlink.pid" + " ORDER BY ancestor.generation;", + fnid + ); + + if( iLimit==0 ) iLimit = 1000000000; + while( iLimit>cnt && db_step(&q)==SQLITE_ROW ){ + rid = db_column_int(&q, 4); + if( cnt==0 ){ + if( !content_get(rid, &toAnnotate) ){ + fossil_fatal("unable to retrieve content of artifact #%d", rid); + } + blob_to_utf8_no_bom(&toAnnotate, 0); + annotation_start(p, &toAnnotate, annFlags); + } p->aVers = fossil_realloc(p->aVers, (p->nVers+1)*sizeof(p->aVers[0])); p->aVers[p->nVers].zFUuid = fossil_strdup(db_column_text(&q, 0)); p->aVers[p->nVers].zMUuid = fossil_strdup(db_column_text(&q, 1)); p->aVers[p->nVers].zDate = fossil_strdup(db_column_text(&q, 2)); p->aVers[p->nVers].zUser = fossil_strdup(db_column_text(&q, 3)); - if( p->nVers ){ + p->nVers++; + if( cnt>0 ){ content_get(rid, &step); blob_to_utf8_no_bom(&step, 0); annotation_step(p, &step, p->nVers-1, annFlags); blob_reset(&step); } - p->nVers++; - db_bind_int(&ins, ":rid", rid); - db_step(&ins); - db_reset(&ins); - db_reset(&q); - rid = prevId; - db_bind_int(&q, ":rid", prevId); cnt++; } p->bLimit = iLimit==cnt; db_finalize(&q); - db_finalize(&ins); db_end_transaction(0); } /* ** Return a color from a gradient. @@ -2297,53 +2299,47 @@ ** ** Query parameters: ** ** checkin=ID The manifest ID at which to start the annotation ** filename=FILENAME The filename. -** filevers Show file versions rather than check-in versions +** filevers=BOOLEAN Show file versions rather than check-in versions ** limit=N Limit the search depth to N ancestors ** log=BOOLEAN Show a log of versions analyzed -** w Ignore whitespace +** w=BOOLEAN Ignore whitespace ** */ void annotation_page(void){ - int mid; - int fnid; int i; int iLimit; /* Depth limit */ u64 annFlags = DIFF_STRIP_EOLCR; - int showLog = 0; /* True to display the log */ - int ignoreWs = 0; /* Ignore whitespace */ + int showLog; /* True to display the log */ + int fileVers; /* Show file version instead of check-in versions */ + int ignoreWs; /* Ignore whitespace */ const char *zFilename; /* Name of file to annotate */ + const char *zRevision; /* Name of check-in from which to start annotation */ const char *zCI; /* The check-in containing zFilename */ Annotator ann; HQuery url; struct AnnVers *p; unsigned clr1, clr2, clr; int bBlame = g.zPath[0]!='a';/* True for BLAME output. False for ANNOTATE. */ /* Gather query parameters */ - showLog = atoi(PD("log","1")); login_check_credentials(); if( !g.perm.Read ){ login_needed(g.anon.Read); return; } if( exclude_spiders() ) return; load_control(); - mid = name_to_typed_rid(PD("checkin","0"),"ci"); zFilename = P("filename"); - fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); - if( mid==0 || fnid==0 ){ fossil_redirect_home(); } + zRevision = PD("checkin",0); iLimit = atoi(PD("limit","20")); - if( P("filevers") ) annFlags |= ANN_FILE_VERS; - ignoreWs = P("w")!=0; + showLog = PB("log"); + fileVers = PB("filevers"); + ignoreWs = PB("w"); if( ignoreWs ) annFlags |= DIFF_IGNORE_ALLWS; - if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ - fossil_redirect_home(); - } /* compute the annotation */ - compute_direct_ancestors(mid); - annotate_file(&ann, fnid, mid, iLimit, annFlags); + annotate_file(&ann, zFilename, zRevision, iLimit, annFlags); zCI = ann.aVers[0].zMUuid; /* generate the web page */ style_header("Annotation For %h", zFilename); if( bBlame ){ @@ -2354,24 +2350,16 @@ url_add_parameter(&url, "checkin", P("checkin")); url_add_parameter(&url, "filename", zFilename); if( iLimit!=20 ){ url_add_parameter(&url, "limit", sqlite3_mprintf("%d", iLimit)); } + url_add_parameter(&url, "w", ignoreWs ? "1" : "0"); url_add_parameter(&url, "log", showLog ? "1" : "0"); - if( ignoreWs ){ - url_add_parameter(&url, "w", ""); - style_submenu_element("Show Whitespace Changes", "%s", - url_render(&url, "w", 0, 0, 0)); - }else{ - style_submenu_element("Ignore Whitespace", "%s", - url_render(&url, "w", "", 0, 0)); - } - if( showLog ){ - style_submenu_element("Hide Log", "%s", url_render(&url, "log", "0", 0, 0)); - }else{ - style_submenu_element("Show Log", "%s", url_render(&url, "log", "1", 0, 0)); - } + url_add_parameter(&url, "filevers", fileVers ? "1" : "0"); + style_submenu_checkbox("w", "Ignore Whitespace", 0); + style_submenu_checkbox("log", "Log", 0); + style_submenu_checkbox("filevers", "Link to Files", 0); if( ann.bLimit ){ char *z1, *z2; style_submenu_element("All Ancestors", "%s", url_render(&url, "limit", "-1", 0, 0)); z1 = sqlite3_mprintf("%d Ancestors", iLimit+20); @@ -2441,27 +2429,29 @@ if( iLimit>ann.nVers && iVers<0 ) iVers = ann.nVers-1; if( bBlame ){ if( iVers>=0 ){ struct AnnVers *p = ann.aVers+iVers; - char *zLink = xhref("target='infowindow'", "%R/info/%!S", p->zMUuid); + const char *zUuid = fileVers ? p->zFUuid : p->zMUuid; + char *zLink = xhref("target='infowindow'", "%R/info/%!S", zUuid); sqlite3_snprintf(sizeof(zPrefix), zPrefix, "" "%s%.10s %s %13.13s:", - p->zBgColor, zLink, p->zMUuid, p->zDate, p->zUser); + p->zBgColor, zLink, zUuid, p->zDate, p->zUser); fossil_free(zLink); }else{ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%36s", ""); } }else{ if( iVers>=0 ){ struct AnnVers *p = ann.aVers+iVers; - char *zLink = xhref("target='infowindow'", "%R/info/%!S", p->zMUuid); + const char *zUuid = fileVers ? p->zFUuid : p->zMUuid; + char *zLink = xhref("target='infowindow'", "%R/info/%!S", zUuid); sqlite3_snprintf(sizeof(zPrefix), zPrefix, "" "%s%.10s %s %4d:", - p->zBgColor, zLink, p->zMUuid, p->zDate, i+1); + p->zBgColor, zLink, zUuid, p->zDate, i+1); fossil_free(zLink); }else{ sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%22s%4d:", "", i+1); } } @@ -2495,33 +2485,26 @@ ** -Z|--ignore-trailing-space Ignore whitespace at line end ** ** See also: info, finfo, timeline */ void annotate_cmd(void){ - int fnid; /* Filename ID */ - int fid; /* File instance ID */ - int mid; /* Manifest where file was checked in */ - int cid; /* Checkout or selected check-in ID */ - Blob treename; /* FILENAME translated to canonical form */ - const char *zRev; /* Revision name, or NULL for current check-in */ - char *zFilename; /* Canonical filename */ + const char *zRevision; /* Revision name, or NULL for current check-in */ Annotator ann; /* The annotation of the file */ int i; /* Loop counter */ const char *zLimit; /* The value to the -n|--limit option */ int iLimit; /* How far back in time to look */ int showLog; /* True to show the log */ int fileVers; /* Show file version instead of check-in versions */ u64 annFlags = 0; /* Flags to control annotation properties */ int bBlame = 0; /* True for BLAME output. False for ANNOTATE. */ - Manifest *pManifest; /* Manifest structure */ - ManifestFile *pFile; /* Manifest file pointer */ bBlame = g.argv[1][0]!='a'; - zRev = find_option("r","revision",1); + zRevision = find_option("r","revision",1); zLimit = find_option("limit","n",1); if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; iLimit = atoi(zLimit); + if( iLimit<=0 ) iLimit = 1000000000; showLog = find_option("log","l",0)!=0; if( find_option("ignore-trailing-space","Z",0)!=0 ){ annFlags = DIFF_IGNORE_EOLWS; } if( find_option("ignore-all-space","w",0)!=0 ){ @@ -2535,65 +2518,12 @@ if( g.argc<3 ) { usage("FILENAME"); } - /* Get filename ID */ - file_tree_name(g.argv[2], &treename, 0, 1); - zFilename = blob_str(&treename); - fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename); - if( fnid==0 ){ - fossil_fatal("no such file: %s", zFilename); - } - - /* Get artifact IDs of selected check-in and file */ - if( zRev ){ - /* Get artifact ID of selected check-in manifest */ - cid = name_to_typed_rid(zRev, "ci"); - - /* Get manifest structure for selected check-in */ - pManifest = manifest_get(cid, CFTYPE_MANIFEST, 0); - if( !pManifest ){ - fossil_fatal("could not parse manifest for check-in: %s", zRev); - } - - /* Get selected file in manifest */ - pFile = manifest_file_find(pManifest, zFilename); - if( !pFile ){ - fossil_fatal("file %s does not exist in check-in %s", zFilename, zRev); - } - manifest_destroy(pManifest); - - /* Get file instance ID from manifest file record */ - fid = fast_uuid_to_rid(pFile->zUuid); - }else{ - /* Get artifact ID of current checkout manifest */ - cid = db_lget_int("checkout", 0); - if( cid == 0 ){ - fossil_fatal("not in a checkout"); - } - - /* Get file instance ID from current checkout file table */ - fid = db_int(0, "SELECT rid FROM vfile WHERE pathname=%Q", zFilename); - if( fid==0 ){ - fossil_fatal("not part of current checkout: %s", zFilename); - } - } - - /* Get ID of most recent manifest containing a change to the selected file */ - compute_direct_ancestors(cid); - mid = db_int(0, "SELECT mlink.mid FROM mlink, ancestor " - " WHERE mlink.fid=%d AND mlink.fnid=%d AND mlink.mid=ancestor.rid" - " ORDER BY ancestor.generation ASC LIMIT 1", - fid, fnid); - if( mid==0 ){ - fossil_fatal("unable to find manifest"); - } - - if( iLimit<=0 ) iLimit = 1000000000; annFlags |= DIFF_STRIP_EOLCR; - annotate_file(&ann, fnid, mid, iLimit, annFlags); + annotate_file(&ann, g.argv[2], zRevision, iLimit, annFlags); if( showLog ){ struct AnnVers *p; for(p=ann.aVers, i=0; izDate, p->zMUuid, p->zFUuid); Index: src/info.c ================================================================== --- src/info.c +++ src/info.c @@ -1071,20 +1071,20 @@ ** branch=TAG Show all changes on a particular branch ** v=BOOLEAN Default true. If false, only list files that have changed ** sbs=BOOLEAN Side-by-side diff if true. Unified diff if false ** glob=STRING only diff files matching this glob ** dc=N show N lines of context around each diff -** w ignore whitespace when computing diffs +** w=BOOLEAN ignore whitespace when computing diffs ** nohdr omit the description at the top of the page ** ** ** Show all differences between two check-ins. */ void vdiff_page(void){ int ridFrom, ridTo; - int verboseFlag = 0; - int sideBySide = 0; + int verboseFlag; + int sideBySide; u64 diffFlags = 0; Manifest *pFrom, *pTo; ManifestFile *pFileFrom, *pFileTo; const char *zBranch; const char *zFrom; @@ -1154,21 +1154,11 @@ sideBySide, (verboseFlag && !sideBySide)?"&v":"", zW); }else{ style_submenu_element("Patch", "%R/vpatch?from=%T&to=%T%s", zFrom, zTo, zW); } if( sideBySide || verboseFlag ){ - if( *zW ){ - style_submenu_element("Show Whitespace Differences", - "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T", zFrom, zTo, - sideBySide, (verboseFlag && !sideBySide)?"&v":"", - zGlob ? "&glob=" : "", zGlob ? zGlob : ""); - }else{ - style_submenu_element("Ignore Whitespace", - "%R/vdiff?from=%T&to=%T&sbs=%d%s%s%T&w", zFrom, zTo, - sideBySide, (verboseFlag && !sideBySide)?"&v":"", - zGlob ? "&glob=" : "", zGlob ? zGlob : ""); - } + style_submenu_checkbox("w", "Ignore Whitespace", 0); } style_header("Check-in Differences"); if( P("nohdr")==0 ){ @

Difference From:

checkin_description(ridFrom); @@ -1546,25 +1536,25 @@ ** "ci" parameter is omitted, then the most recent check-in ("tip") is ** used. ** ** Additional parameters: ** -** dc=N Show N lines of context around each diff -** patch Use the patch diff format -** regex=REGEX Only show differences that match REGEX -** sbs=BOOLEAN Turn side-by-side diffs on and off (default: on) -** verbose Show more detail when describing artifacts -** w Ignore whitespace +** dc=N Show N lines of context around each diff +** patch Use the patch diff format +** regex=REGEX Only show differences that match REGEX +** sbs=BOOLEAN Turn side-by-side diffs on and off (default: on) +** verbose=BOOLEAN Show more detail when describing artifacts +** w=BOOLEAN Ignore whitespace */ void diff_page(void){ int v1, v2; - int isPatch; - int sideBySide; + int isPatch = P("patch")!=0; + int sideBySide = PB("sbs"); + int verbose = PB("verbose"); char *zV1; char *zV2; const char *zRe; - const char *zW; /* URL param for ignoring whitespace */ ReCompiled *pRe = 0; u64 diffFlags; u32 objdescFlags = 0; login_check_credentials(); @@ -1577,12 +1567,11 @@ v2 = name_to_rid_www("v2"); } if( v1==0 || v2==0 ) fossil_redirect_home(); zRe = P("regex"); if( zRe ) re_compile(&pRe, zRe, 0); - if( P("verbose")!=0 ) objdescFlags |= OBJDESC_DETAIL; - isPatch = P("patch")!=0; + if( verbose ) objdescFlags |= OBJDESC_DETAIL; if( isPatch ){ Blob c1, c2, *pOut; pOut = cgi_output_blob(); cgi_set_content_type("text/plain"); diffFlags = 4; @@ -1592,37 +1581,20 @@ blob_reset(&c1); blob_reset(&c2); return; } - sideBySide = !is_false(PD("sbs","1")); zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); diffFlags = construct_diff_flags(1, sideBySide) | DIFF_HTML; style_header("Diff"); - zW = (diffFlags&DIFF_IGNORE_ALLWS)?"&w":""; - if( *zW ){ - style_submenu_element("Show Whitespace Changes", - "%s/fdiff?v1=%T&v2=%T&sbs=%d", - g.zTop, P("v1"), P("v2"), sideBySide); - }else{ - style_submenu_element("Ignore Whitespace", - "%s/fdiff?v1=%T&v2=%T&sbs=%d&w", - g.zTop, P("v1"), P("v2"), sideBySide); - } + style_submenu_checkbox("w", "Ignore Whitespace", 0); + style_submenu_checkbox("sbs", "Side-by-Side Diff", 0); + style_submenu_checkbox("verbose", "Verbose", 0); style_submenu_element("Patch", "%s/fdiff?v1=%T&v2=%T&patch", g.zTop, P("v1"), P("v2")); - if( !sideBySide ){ - style_submenu_element("Side-by-Side Diff", - "%s/fdiff?v1=%T&v2=%T&sbs=1%s", - g.zTop, P("v1"), P("v2"), zW); - }else{ - style_submenu_element("Unified Diff", - "%s/fdiff?v1=%T&v2=%T&sbs=0%s", - g.zTop, P("v1"), P("v2"), zW); - } if( P("smhdr")!=0 ){ @

Differences From Artifact @ %z(href("%R/artifact/%!S",zV1))[%S(zV1)] To @ %z(href("%R/artifact/%!S",zV2))[%S(zV2)].

Index: www/globs.md ================================================================== --- www/globs.md +++ www/globs.md @@ -48,14 +48,16 @@ Special characters (and special character sequences) consume zero or more characters from the target and describe what matches. The special characters (and sequences) are: - * `*` Matches any sequence of zero or more characters; - * `?` Matches exactly one character; - * `[...]` Matches one character from the enclosed list of characters; and - * `[^...]` Matches one character not in the enclosed list. +:Pattern |:Effect +--------------------------------------------------------------------- +`*` | Matches any sequence of zero or more characters +`?` | Matches exactly one character +`[...]` | Matches one character from the enclosed list of characters +`[^...]` | Matches one character not in the enclosed list Special character sequences have some additional features: * A range of characters may be specified with `-`, so `[a-d]` matches exactly the same characters as `[abcd]`. Ranges reflect Unicode @@ -77,19 +79,20 @@ separators as well as the initial `.` in the name of a hidden file or directory. Some examples of character lists: - * `[a-d]` Matches any one of `a`, `b`, `c`, or `d` but not `ä`; - * `[^a-d]` Matches exactly one character other than `a`, `b`, `c`, - or `d`; - * `[0-9a-fA-F]` Matches exactly one hexadecimal digit; - * `[a-]` Matches either `a` or `-`; - * `[][]` Matches either `]` or `[`; - * `[^]]` Matches exactly one character other than `]`; - * `[]^]` Matches either `]` or `^`; and - * `[^-]` Matches exactly one character other than `-`. +:Pattern |:Effect +--------------------------------------------------------------------- +`[a-d]` | Matches any one of `a`, `b`, `c`, or `d` but not `ä` +`[^a-d]` | Matches exactly one character other than `a`, `b`, `c`, or `d` +`[0-9a-fA-F]` | Matches exactly one hexadecimal digit +`[a-]` | Matches either `a` or `-` +`[][]` | Matches either `]` or `[` +`[^]]` | Matches exactly one character other than `]` +`[]^]` | Matches either `]` or `^` +`[^-]` | Matches exactly one character other than `-` White space means the specific ASCII characters TAB, LF, VT, FF, CR, and SPACE. Note that this does not include any of the many additional spacing characters available in Unicode, and specifically does not include U+00A0 NO-BREAK SPACE. @@ -127,44 +130,33 @@ case insensitive. That is, on Windows, the names `ReadMe` and `README` are names of the same file; on Unix they are different files. Some example cases: - * The glob `README` matches only a file named `README` in the root of - the tree. It does not match a file named `src/README` because it - does not include any characters that consume (and match) the - `src/` part. - * The glob `*/README` does match `src/README`. Unlike Unix file - globs, it also matches `src/library/README`. However it does not - match the file `README` in the root of the tree. - * The glob `*README` does match `src/README` as well as the file - `README` in the root of the tree as well as `foo/bar/README` or - any other file named `README` in the tree. However, it also - matches `A-DIFFERENT-README` and `src/DO-NOT-README`, or any other - file whose name ends with `README`. - * The glob `src/README` does match the file named `src\README` on - Windows because all directory separators are rewritten as `/` in - the canonical name before the glob is matched. This makes it much - easier to write globs that work on both Unix and Windows. - * The glob `*.[ch]` matches every C source or header file in the - tree at the root or at any depth. Again, this is (deliberately) - different from Unix file globs and Windows wild cards. - +:Pattern |:Effect +-------------------------------------------------------------------------------- +`README` | Matches only a file named `README` in the root of the tree. It does not match a file named `src/README` because it does not include any characters that consume (and match) the `src/` part. +`*/README` | Matches `src/README`. Unlike Unix file globs, it also matches `src/library/README`. However it does not match the file `README` in the root of the tree. +`*README` | Matches `src/README` as well as the file `README` in the root of the tree as well as `foo/bar/README` or any other file named `README` in the tree. However, it also matches `A-DIFFERENT-README` and `src/DO-NOT-README`, or any other file whose name ends with `README`. +`src/README` | Matches `src\README` on Windows because all directory separators are rewritten as `/` in the canonical name before the glob is matched. This makes it much easier to write globs that work on both Unix and Windows. +`*.[ch]` | Matches every C source or header file in the tree at the root or at any depth. Again, this is (deliberately) different from Unix file globs and Windows wild cards. ## Where Globs are Used ### Settings that are Globs These settings are all lists of glob patterns: - * `binary-glob` - * `clean-glob` - * `crlf-glob` - * `crnl-glob` - * `encoding-glob` - * `ignore-glob` - * `keep-glob` +:Setting |:Description +-------------------------------------------------------------------------------- +`binary-glob` | Files that should be treated as binary files for committing and merging purposes +`clean-glob` | Files that the [`clean`][] command will delete without prompting or allowing undo +`crlf-glob` | Files in which it is okay to have `CR`, `CR`+`LF` or mixed line endings. Set to "`*`" to disable CR+LF checking +`crnl-glob` | Alias for the `crlf-glob` setting +`encoding-glob` | Files that the [`commit`][] command will ignore when issuing warnings about text files that may use another encoding than ASCII or UTF-8. Set to "`*`" to disable encoding checking +`ignore-glob` | Files that the [`add`][], [`addremove`][], [`clean`][], and [`extras`][] commands will ignore +`keep-glob` | Files that the [`clean`][] command will keep All may be [versioned, local, or global](settings.wiki). Use `fossil settings` to manage local and global settings, or a file in the repository's `.fossil-settings/` folder at the root of the tree named for each for versioned setting. @@ -191,10 +183,11 @@ * [`add`][] * [`addremove`][] * [`changes`][] * [`clean`][] + * [`commit`][] * [`extras`][] * [`merge`][] * [`settings`][] * [`status`][] * [`unset`][] @@ -211,10 +204,11 @@ [`add`]: /help?cmd=add [`addremove`]: /help?cmd=addremove [`changes`]: /help?cmd=changes [`clean`]: /help?cmd=clean +[`commit`]: /help?cmd=commit [`extras`]: /help?cmd=extras [`merge`]: /help?cmd=merge [`settings`]: /help?cmd=settings [`status`]: /help?cmd=status [`unset`]: /help?cmd=unset @@ -517,24 +511,21 @@ front of the function that implements the command or page in files `src/*.c`. (Fossil's build system creates the tables used to dispatch commands at build time by searching the sources for those comments.) A few starting points: - * [`src/glob.c`][glob.c] implements glob pattern list loading, - parsing, and matching. - * [`src/file.c`][file.c] implements various kinds of canonical - names of a file. - - -[glob.c]: https://www.fossil-scm.org/index.html/file/src/glob.c -[file.c]: https://www.fossil-scm.org/index.html/file/src/file.c +:File |:Description +-------------------------------------------------------------------------------- +[`src/glob.c`][] | Implementation of glob pattern list loading, parsing, and matching. +[`src/file.c`][] | Implementation of various kinds of canonical names of a file. + +[`src/glob.c`]: https://www.fossil-scm.org/index.html/file/src/glob.c +[`src/file.c`]: https://www.fossil-scm.org/index.html/file/src/file.c The actual pattern matching is implemented in SQL, so the documentation for `GLOB` and the other string matching operators in [SQLite] (https://sqlite.org/lang_expr.html#like) is useful. Of -course, the SQLite source code and test harnesses also make -entertaining reading: - - * `src/func.c` [lines 570-768] - (https://www.sqlite.org/src/artifact?name=9d52522cc8ae7f5c&ln=570-768) - * `test/expr.test` [lines 586-673] - (https://www.sqlite.org/src/artifact?name=66a2c9ac34f74f03&ln=586-673) +course, the SQLite [source code] +(https://www.sqlite.org/src/artifact?name=9d52522cc8ae7f5c&ln=570-768) +and [test harnesses] +(https://www.sqlite.org/src/artifact?name=66a2c9ac34f74f03&ln=586-673) +also make entertaining reading.