Fossil SCM
Merge from trunk
Commit
959699bfb6f13990feab7f68f31d67870bfda051d0af248efd59522206d9642c
Parent
df330b709f28be4…
17 files changed
+1
-1
+5
-3
+11
-4
+29
-13
+4
+16
-11
+6
-2
-1
+4
-4
+1
-1
+3
-2
+18
+26
-38
+90
-84
+61
-13
+28
-45
+15
~
src/backoffice.c
~
src/builtin.c
~
src/cgi.c
~
src/clone.c
~
src/extcgi.c
~
src/fossil.fetch.js
~
src/login.c
~
src/sqlcmd.c
~
src/timeline.c
~
src/tktsetup.c
~
www/backup.md
~
www/changes.wiki
~
www/ckout-workflows.md
~
www/fossil-v-git.wiki
~
www/gitusers.md
~
www/rebaseharm.md
~
www/serverext.wiki
+1
-1
| --- src/backoffice.c | ||
| +++ src/backoffice.c | ||
| @@ -461,11 +461,11 @@ | ||
| 461 | 461 | ** |
| 462 | 462 | ** If no backoffice processes are running at all, this routine becomes |
| 463 | 463 | ** the main backoffice. |
| 464 | 464 | ** |
| 465 | 465 | ** If a primary backoffice is running, but a on-deck backoffice is |
| 466 | -** needed, this routine becomes that on-desk backoffice. | |
| 466 | +** needed, this routine becomes that on-deck backoffice. | |
| 467 | 467 | */ |
| 468 | 468 | static void backoffice_thread(void){ |
| 469 | 469 | Lease x; |
| 470 | 470 | sqlite3_uint64 tmNow; |
| 471 | 471 | sqlite3_uint64 idSelf; |
| 472 | 472 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -461,11 +461,11 @@ | |
| 461 | ** |
| 462 | ** If no backoffice processes are running at all, this routine becomes |
| 463 | ** the main backoffice. |
| 464 | ** |
| 465 | ** If a primary backoffice is running, but a on-deck backoffice is |
| 466 | ** needed, this routine becomes that on-desk backoffice. |
| 467 | */ |
| 468 | static void backoffice_thread(void){ |
| 469 | Lease x; |
| 470 | sqlite3_uint64 tmNow; |
| 471 | sqlite3_uint64 idSelf; |
| 472 |
| --- src/backoffice.c | |
| +++ src/backoffice.c | |
| @@ -461,11 +461,11 @@ | |
| 461 | ** |
| 462 | ** If no backoffice processes are running at all, this routine becomes |
| 463 | ** the main backoffice. |
| 464 | ** |
| 465 | ** If a primary backoffice is running, but a on-deck backoffice is |
| 466 | ** needed, this routine becomes that on-deck backoffice. |
| 467 | */ |
| 468 | static void backoffice_thread(void){ |
| 469 | Lease x; |
| 470 | sqlite3_uint64 tmNow; |
| 471 | sqlite3_uint64 idSelf; |
| 472 |
+5
-3
| --- src/builtin.c | ||
| +++ src/builtin.c | ||
| @@ -775,13 +775,15 @@ | ||
| 775 | 775 | ** initialize the window.fossil JS API. The first argument is the NAME |
| 776 | 776 | ** part of the first API to emit. All subsequent arguments must be |
| 777 | 777 | ** strings of the NAME part of additional fossil.NAME.js files, |
| 778 | 778 | ** followed by a NULL argument to terminate the list. |
| 779 | 779 | ** |
| 780 | -** e.g. pass it ("fetch", "dom", "tabs", 0) to load those 3 APIs (or | |
| 781 | -** pass it ("fetch","tabs",0), as "dom" is a dependency of "tabs", so | |
| 782 | -** it will be automatically loaded). Do not forget the trailing 0! | |
| 780 | +** e.g. pass it ("fetch", "dom", "tabs", NULL) to load those 3 APIs (or | |
| 781 | +** pass it ("fetch","tabs",NULL), as "dom" is a dependency of "tabs", so | |
| 782 | +** it will be automatically loaded). Do not forget the trailing NULL, | |
| 783 | +** and do not pass 0 instead, since that isn't always equivalent to NULL | |
| 784 | +** in this context. | |
| 783 | 785 | ** |
| 784 | 786 | ** If it is JS_BUNDLED then this routine queues up an emit of ALL of |
| 785 | 787 | ** the JS fossil.XYZ.js APIs which are not strictly specific to a |
| 786 | 788 | ** single page, and then calls builtin_fulfill_js_requests(). The idea |
| 787 | 789 | ** is that we can get better bundle caching and reduced HTTP requests |
| 788 | 790 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -775,13 +775,15 @@ | |
| 775 | ** initialize the window.fossil JS API. The first argument is the NAME |
| 776 | ** part of the first API to emit. All subsequent arguments must be |
| 777 | ** strings of the NAME part of additional fossil.NAME.js files, |
| 778 | ** followed by a NULL argument to terminate the list. |
| 779 | ** |
| 780 | ** e.g. pass it ("fetch", "dom", "tabs", 0) to load those 3 APIs (or |
| 781 | ** pass it ("fetch","tabs",0), as "dom" is a dependency of "tabs", so |
| 782 | ** it will be automatically loaded). Do not forget the trailing 0! |
| 783 | ** |
| 784 | ** If it is JS_BUNDLED then this routine queues up an emit of ALL of |
| 785 | ** the JS fossil.XYZ.js APIs which are not strictly specific to a |
| 786 | ** single page, and then calls builtin_fulfill_js_requests(). The idea |
| 787 | ** is that we can get better bundle caching and reduced HTTP requests |
| 788 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -775,13 +775,15 @@ | |
| 775 | ** initialize the window.fossil JS API. The first argument is the NAME |
| 776 | ** part of the first API to emit. All subsequent arguments must be |
| 777 | ** strings of the NAME part of additional fossil.NAME.js files, |
| 778 | ** followed by a NULL argument to terminate the list. |
| 779 | ** |
| 780 | ** e.g. pass it ("fetch", "dom", "tabs", NULL) to load those 3 APIs (or |
| 781 | ** pass it ("fetch","tabs",NULL), as "dom" is a dependency of "tabs", so |
| 782 | ** it will be automatically loaded). Do not forget the trailing NULL, |
| 783 | ** and do not pass 0 instead, since that isn't always equivalent to NULL |
| 784 | ** in this context. |
| 785 | ** |
| 786 | ** If it is JS_BUNDLED then this routine queues up an emit of ALL of |
| 787 | ** the JS fossil.XYZ.js APIs which are not strictly specific to a |
| 788 | ** single page, and then calls builtin_fulfill_js_requests(). The idea |
| 789 | ** is that we can get better bundle caching and reduced HTTP requests |
| 790 |
+11
-4
| --- src/cgi.c | ||
| +++ src/cgi.c | ||
| @@ -1427,14 +1427,14 @@ | ||
| 1427 | 1427 | "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHENICATION", |
| 1428 | 1428 | "HTTP_CONNECTION", "HTTP_HOST", |
| 1429 | 1429 | "HTTP_IF_NONE_MATCH", "HTTP_IF_MODIFIED_SINCE", |
| 1430 | 1430 | "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED", |
| 1431 | 1431 | "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", |
| 1432 | - "REMOTE_USER", "REQUEST_METHOD", | |
| 1433 | - "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_PROTOCOL", | |
| 1434 | - "HOME", "FOSSIL_HOME", "USERNAME", "USER", "FOSSIL_USER", | |
| 1435 | - "SQLITE_TMPDIR", "TMPDIR", | |
| 1432 | + "REMOTE_USER", "REQUEST_METHOD", "REQUEST_SCHEME", | |
| 1433 | + "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_NAME", | |
| 1434 | + "SERVER_PROTOCOL", "HOME", "FOSSIL_HOME", "USERNAME", "USER", | |
| 1435 | + "FOSSIL_USER", "SQLITE_TMPDIR", "TMPDIR", | |
| 1436 | 1436 | "TEMP", "TMP", "FOSSIL_VFS", |
| 1437 | 1437 | "FOSSIL_FORCE_TICKET_MODERATION", "FOSSIL_FORCE_WIKI_MODERATION", |
| 1438 | 1438 | "FOSSIL_TCL_PATH", "TH1_DELETE_INTERP", "TH1_ENABLE_DOCS", |
| 1439 | 1439 | "TH1_ENABLE_HOOKS", "TH1_ENABLE_TCL", "REMOTE_HOST", |
| 1440 | 1440 | }; |
| @@ -1662,10 +1662,11 @@ | ||
| 1662 | 1662 | ** and subsequent code handles the actual generation of the webpage. |
| 1663 | 1663 | */ |
| 1664 | 1664 | void cgi_handle_http_request(const char *zIpAddr){ |
| 1665 | 1665 | char *z, *zToken; |
| 1666 | 1666 | int i; |
| 1667 | + const char *zScheme = "http"; | |
| 1667 | 1668 | char zLine[2000]; /* A single line of input. */ |
| 1668 | 1669 | g.fullHttpReply = 1; |
| 1669 | 1670 | if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ |
| 1670 | 1671 | malformed_request("missing HTTP header"); |
| 1671 | 1672 | } |
| @@ -1725,12 +1726,17 @@ | ||
| 1725 | 1726 | cgi_setenv("CONTENT_TYPE", zVal); |
| 1726 | 1727 | }else if( fossil_strcmp(zFieldName,"cookie:")==0 ){ |
| 1727 | 1728 | cgi_setenv("HTTP_COOKIE", zVal); |
| 1728 | 1729 | }else if( fossil_strcmp(zFieldName,"https:")==0 ){ |
| 1729 | 1730 | cgi_setenv("HTTPS", zVal); |
| 1731 | + zScheme = "https"; | |
| 1730 | 1732 | }else if( fossil_strcmp(zFieldName,"host:")==0 ){ |
| 1733 | + char *z; | |
| 1731 | 1734 | cgi_setenv("HTTP_HOST", zVal); |
| 1735 | + z = strchr(zVal, ':'); | |
| 1736 | + if( z ) z[0] = 0; | |
| 1737 | + cgi_setenv("SERVER_NAME", zVal); | |
| 1732 | 1738 | }else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){ |
| 1733 | 1739 | cgi_setenv("HTTP_IF_NONE_MATCH", zVal); |
| 1734 | 1740 | }else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){ |
| 1735 | 1741 | cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal); |
| 1736 | 1742 | }else if( fossil_strcmp(zFieldName,"referer:")==0 ){ |
| @@ -1752,10 +1758,11 @@ | ||
| 1752 | 1758 | rangeStart = x1; |
| 1753 | 1759 | rangeEnd = x2+1; |
| 1754 | 1760 | } |
| 1755 | 1761 | } |
| 1756 | 1762 | } |
| 1763 | + cgi_setenv("REQUEST_SCHEME",zScheme); | |
| 1757 | 1764 | cgi_init(); |
| 1758 | 1765 | cgi_trace(0); |
| 1759 | 1766 | } |
| 1760 | 1767 | |
| 1761 | 1768 | /* |
| 1762 | 1769 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1427,14 +1427,14 @@ | |
| 1427 | "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHENICATION", |
| 1428 | "HTTP_CONNECTION", "HTTP_HOST", |
| 1429 | "HTTP_IF_NONE_MATCH", "HTTP_IF_MODIFIED_SINCE", |
| 1430 | "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED", |
| 1431 | "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", |
| 1432 | "REMOTE_USER", "REQUEST_METHOD", |
| 1433 | "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_PROTOCOL", |
| 1434 | "HOME", "FOSSIL_HOME", "USERNAME", "USER", "FOSSIL_USER", |
| 1435 | "SQLITE_TMPDIR", "TMPDIR", |
| 1436 | "TEMP", "TMP", "FOSSIL_VFS", |
| 1437 | "FOSSIL_FORCE_TICKET_MODERATION", "FOSSIL_FORCE_WIKI_MODERATION", |
| 1438 | "FOSSIL_TCL_PATH", "TH1_DELETE_INTERP", "TH1_ENABLE_DOCS", |
| 1439 | "TH1_ENABLE_HOOKS", "TH1_ENABLE_TCL", "REMOTE_HOST", |
| 1440 | }; |
| @@ -1662,10 +1662,11 @@ | |
| 1662 | ** and subsequent code handles the actual generation of the webpage. |
| 1663 | */ |
| 1664 | void cgi_handle_http_request(const char *zIpAddr){ |
| 1665 | char *z, *zToken; |
| 1666 | int i; |
| 1667 | char zLine[2000]; /* A single line of input. */ |
| 1668 | g.fullHttpReply = 1; |
| 1669 | if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ |
| 1670 | malformed_request("missing HTTP header"); |
| 1671 | } |
| @@ -1725,12 +1726,17 @@ | |
| 1725 | cgi_setenv("CONTENT_TYPE", zVal); |
| 1726 | }else if( fossil_strcmp(zFieldName,"cookie:")==0 ){ |
| 1727 | cgi_setenv("HTTP_COOKIE", zVal); |
| 1728 | }else if( fossil_strcmp(zFieldName,"https:")==0 ){ |
| 1729 | cgi_setenv("HTTPS", zVal); |
| 1730 | }else if( fossil_strcmp(zFieldName,"host:")==0 ){ |
| 1731 | cgi_setenv("HTTP_HOST", zVal); |
| 1732 | }else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){ |
| 1733 | cgi_setenv("HTTP_IF_NONE_MATCH", zVal); |
| 1734 | }else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){ |
| 1735 | cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal); |
| 1736 | }else if( fossil_strcmp(zFieldName,"referer:")==0 ){ |
| @@ -1752,10 +1758,11 @@ | |
| 1752 | rangeStart = x1; |
| 1753 | rangeEnd = x2+1; |
| 1754 | } |
| 1755 | } |
| 1756 | } |
| 1757 | cgi_init(); |
| 1758 | cgi_trace(0); |
| 1759 | } |
| 1760 | |
| 1761 | /* |
| 1762 |
| --- src/cgi.c | |
| +++ src/cgi.c | |
| @@ -1427,14 +1427,14 @@ | |
| 1427 | "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHENICATION", |
| 1428 | "HTTP_CONNECTION", "HTTP_HOST", |
| 1429 | "HTTP_IF_NONE_MATCH", "HTTP_IF_MODIFIED_SINCE", |
| 1430 | "HTTP_USER_AGENT", "HTTP_REFERER", "PATH_INFO", "PATH_TRANSLATED", |
| 1431 | "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT", |
| 1432 | "REMOTE_USER", "REQUEST_METHOD", "REQUEST_SCHEME", |
| 1433 | "REQUEST_URI", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_NAME", |
| 1434 | "SERVER_PROTOCOL", "HOME", "FOSSIL_HOME", "USERNAME", "USER", |
| 1435 | "FOSSIL_USER", "SQLITE_TMPDIR", "TMPDIR", |
| 1436 | "TEMP", "TMP", "FOSSIL_VFS", |
| 1437 | "FOSSIL_FORCE_TICKET_MODERATION", "FOSSIL_FORCE_WIKI_MODERATION", |
| 1438 | "FOSSIL_TCL_PATH", "TH1_DELETE_INTERP", "TH1_ENABLE_DOCS", |
| 1439 | "TH1_ENABLE_HOOKS", "TH1_ENABLE_TCL", "REMOTE_HOST", |
| 1440 | }; |
| @@ -1662,10 +1662,11 @@ | |
| 1662 | ** and subsequent code handles the actual generation of the webpage. |
| 1663 | */ |
| 1664 | void cgi_handle_http_request(const char *zIpAddr){ |
| 1665 | char *z, *zToken; |
| 1666 | int i; |
| 1667 | const char *zScheme = "http"; |
| 1668 | char zLine[2000]; /* A single line of input. */ |
| 1669 | g.fullHttpReply = 1; |
| 1670 | if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ |
| 1671 | malformed_request("missing HTTP header"); |
| 1672 | } |
| @@ -1725,12 +1726,17 @@ | |
| 1726 | cgi_setenv("CONTENT_TYPE", zVal); |
| 1727 | }else if( fossil_strcmp(zFieldName,"cookie:")==0 ){ |
| 1728 | cgi_setenv("HTTP_COOKIE", zVal); |
| 1729 | }else if( fossil_strcmp(zFieldName,"https:")==0 ){ |
| 1730 | cgi_setenv("HTTPS", zVal); |
| 1731 | zScheme = "https"; |
| 1732 | }else if( fossil_strcmp(zFieldName,"host:")==0 ){ |
| 1733 | char *z; |
| 1734 | cgi_setenv("HTTP_HOST", zVal); |
| 1735 | z = strchr(zVal, ':'); |
| 1736 | if( z ) z[0] = 0; |
| 1737 | cgi_setenv("SERVER_NAME", zVal); |
| 1738 | }else if( fossil_strcmp(zFieldName,"if-none-match:")==0 ){ |
| 1739 | cgi_setenv("HTTP_IF_NONE_MATCH", zVal); |
| 1740 | }else if( fossil_strcmp(zFieldName,"if-modified-since:")==0 ){ |
| 1741 | cgi_setenv("HTTP_IF_MODIFIED_SINCE", zVal); |
| 1742 | }else if( fossil_strcmp(zFieldName,"referer:")==0 ){ |
| @@ -1752,10 +1758,11 @@ | |
| 1758 | rangeStart = x1; |
| 1759 | rangeEnd = x2+1; |
| 1760 | } |
| 1761 | } |
| 1762 | } |
| 1763 | cgi_setenv("REQUEST_SCHEME",zScheme); |
| 1764 | cgi_init(); |
| 1765 | cgi_trace(0); |
| 1766 | } |
| 1767 | |
| 1768 | /* |
| 1769 |
+29
-13
| --- src/clone.c | ||
| +++ src/clone.c | ||
| @@ -123,10 +123,12 @@ | ||
| 123 | 123 | ** the -A|--admin-user parameter. |
| 124 | 124 | ** |
| 125 | 125 | ** Options: |
| 126 | 126 | ** --admin-user|-A USERNAME Make USERNAME the administrator |
| 127 | 127 | ** --httpauth|-B USER:PASS Add HTTP Basic Authorization to requests |
| 128 | +** --nested Allow opening a repository inside an opened | |
| 129 | +** checkout | |
| 128 | 130 | ** --nocompress Omit extra delta compression |
| 129 | 131 | ** --no-open Clone only. Do not open a check-out. |
| 130 | 132 | ** --once Don't remember the URI. |
| 131 | 133 | ** --private Also clone private branches |
| 132 | 134 | ** --save-http-password Remember the HTTP password without asking |
| @@ -145,12 +147,13 @@ | ||
| 145 | 147 | int nErr = 0; |
| 146 | 148 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 147 | 149 | int syncFlags = SYNC_CLONE; |
| 148 | 150 | int noCompress = find_option("nocompress",0,0)!=0; |
| 149 | 151 | int noOpen = find_option("no-open",0,0)!=0; |
| 152 | + int allowNested = find_option("nested",0,0)!=0; /* Used by open */ | |
| 150 | 153 | const char *zRepo = 0; /* Name of the new local repository file */ |
| 151 | - const char *zWorkDir = 0; /* Open in this director, if not zero */ | |
| 154 | + const char *zWorkDir = 0; /* Open in this directory, if not zero */ | |
| 152 | 155 | |
| 153 | 156 | |
| 154 | 157 | /* Also clone private branches */ |
| 155 | 158 | if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; |
| 156 | 159 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| @@ -189,10 +192,16 @@ | ||
| 189 | 192 | } |
| 190 | 193 | fossil_free(zBase); |
| 191 | 194 | } |
| 192 | 195 | if( -1 != file_size(zRepo, ExtFILE) ){ |
| 193 | 196 | fossil_fatal("file already exists: %s", zRepo); |
| 197 | + } | |
| 198 | + /* Fail before clone if open will fail because inside an open checkout */ | |
| 199 | + if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ | |
| 200 | + if( db_open_local_v2(0, allowNested) ){ | |
| 201 | + fossil_fatal("there is already an open tree at %s", g.zLocalRoot); | |
| 202 | + } | |
| 194 | 203 | } |
| 195 | 204 | url_parse(g.argv[2], urlFlags); |
| 196 | 205 | if( zDefaultUser==0 && g.url.user!=0 ) zDefaultUser = g.url.user; |
| 197 | 206 | if( g.url.isFile ){ |
| 198 | 207 | file_copy(g.url.name, zRepo); |
| @@ -277,22 +286,29 @@ | ||
| 277 | 286 | fossil_print("\nproject-id: %s\n", db_get("project-code", 0)); |
| 278 | 287 | fossil_print("server-id: %s\n", db_get("server-code", 0)); |
| 279 | 288 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); |
| 280 | 289 | fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); |
| 281 | 290 | if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ |
| 282 | - char *azNew[6]; | |
| 283 | - fossil_print("opening the new %s repository in directory %s...\n", | |
| 284 | - zRepo, zWorkDir); | |
| 285 | - azNew[0] = g.argv[0]; | |
| 286 | - azNew[1] = "open"; | |
| 287 | - azNew[2] = (char*)zRepo; | |
| 288 | - azNew[3] = "--workdir"; | |
| 289 | - azNew[4] = (char*)zWorkDir; | |
| 290 | - azNew[5] = 0; | |
| 291 | - g.argv = azNew; | |
| 292 | - g.argc = 5; | |
| 293 | - cmd_open(); | |
| 291 | + char *azNew[7]; | |
| 292 | + int nargs = 5; | |
| 293 | + fossil_print("opening the new %s repository in directory %s...\n", | |
| 294 | + zRepo, zWorkDir); | |
| 295 | + azNew[0] = g.argv[0]; | |
| 296 | + azNew[1] = "open"; | |
| 297 | + azNew[2] = (char*)zRepo; | |
| 298 | + azNew[3] = "--workdir"; | |
| 299 | + azNew[4] = (char*)zWorkDir; | |
| 300 | + if( allowNested ){ | |
| 301 | + azNew[5] = "--nested"; | |
| 302 | + nargs++; | |
| 303 | + }else{ | |
| 304 | + azNew[5] = 0; | |
| 305 | + } | |
| 306 | + azNew[6] = 0; | |
| 307 | + g.argv = azNew; | |
| 308 | + g.argc = nargs; | |
| 309 | + cmd_open(); | |
| 294 | 310 | } |
| 295 | 311 | } |
| 296 | 312 | |
| 297 | 313 | /* |
| 298 | 314 | ** If user chooses to use HTTP Authentication over unencrypted HTTP, |
| 299 | 315 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -123,10 +123,12 @@ | |
| 123 | ** the -A|--admin-user parameter. |
| 124 | ** |
| 125 | ** Options: |
| 126 | ** --admin-user|-A USERNAME Make USERNAME the administrator |
| 127 | ** --httpauth|-B USER:PASS Add HTTP Basic Authorization to requests |
| 128 | ** --nocompress Omit extra delta compression |
| 129 | ** --no-open Clone only. Do not open a check-out. |
| 130 | ** --once Don't remember the URI. |
| 131 | ** --private Also clone private branches |
| 132 | ** --save-http-password Remember the HTTP password without asking |
| @@ -145,12 +147,13 @@ | |
| 145 | int nErr = 0; |
| 146 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 147 | int syncFlags = SYNC_CLONE; |
| 148 | int noCompress = find_option("nocompress",0,0)!=0; |
| 149 | int noOpen = find_option("no-open",0,0)!=0; |
| 150 | const char *zRepo = 0; /* Name of the new local repository file */ |
| 151 | const char *zWorkDir = 0; /* Open in this director, if not zero */ |
| 152 | |
| 153 | |
| 154 | /* Also clone private branches */ |
| 155 | if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; |
| 156 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| @@ -189,10 +192,16 @@ | |
| 189 | } |
| 190 | fossil_free(zBase); |
| 191 | } |
| 192 | if( -1 != file_size(zRepo, ExtFILE) ){ |
| 193 | fossil_fatal("file already exists: %s", zRepo); |
| 194 | } |
| 195 | url_parse(g.argv[2], urlFlags); |
| 196 | if( zDefaultUser==0 && g.url.user!=0 ) zDefaultUser = g.url.user; |
| 197 | if( g.url.isFile ){ |
| 198 | file_copy(g.url.name, zRepo); |
| @@ -277,22 +286,29 @@ | |
| 277 | fossil_print("\nproject-id: %s\n", db_get("project-code", 0)); |
| 278 | fossil_print("server-id: %s\n", db_get("server-code", 0)); |
| 279 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); |
| 280 | fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); |
| 281 | if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ |
| 282 | char *azNew[6]; |
| 283 | fossil_print("opening the new %s repository in directory %s...\n", |
| 284 | zRepo, zWorkDir); |
| 285 | azNew[0] = g.argv[0]; |
| 286 | azNew[1] = "open"; |
| 287 | azNew[2] = (char*)zRepo; |
| 288 | azNew[3] = "--workdir"; |
| 289 | azNew[4] = (char*)zWorkDir; |
| 290 | azNew[5] = 0; |
| 291 | g.argv = azNew; |
| 292 | g.argc = 5; |
| 293 | cmd_open(); |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | /* |
| 298 | ** If user chooses to use HTTP Authentication over unencrypted HTTP, |
| 299 |
| --- src/clone.c | |
| +++ src/clone.c | |
| @@ -123,10 +123,12 @@ | |
| 123 | ** the -A|--admin-user parameter. |
| 124 | ** |
| 125 | ** Options: |
| 126 | ** --admin-user|-A USERNAME Make USERNAME the administrator |
| 127 | ** --httpauth|-B USER:PASS Add HTTP Basic Authorization to requests |
| 128 | ** --nested Allow opening a repository inside an opened |
| 129 | ** checkout |
| 130 | ** --nocompress Omit extra delta compression |
| 131 | ** --no-open Clone only. Do not open a check-out. |
| 132 | ** --once Don't remember the URI. |
| 133 | ** --private Also clone private branches |
| 134 | ** --save-http-password Remember the HTTP password without asking |
| @@ -145,12 +147,13 @@ | |
| 147 | int nErr = 0; |
| 148 | int urlFlags = URL_PROMPT_PW | URL_REMEMBER; |
| 149 | int syncFlags = SYNC_CLONE; |
| 150 | int noCompress = find_option("nocompress",0,0)!=0; |
| 151 | int noOpen = find_option("no-open",0,0)!=0; |
| 152 | int allowNested = find_option("nested",0,0)!=0; /* Used by open */ |
| 153 | const char *zRepo = 0; /* Name of the new local repository file */ |
| 154 | const char *zWorkDir = 0; /* Open in this directory, if not zero */ |
| 155 | |
| 156 | |
| 157 | /* Also clone private branches */ |
| 158 | if( find_option("private",0,0)!=0 ) syncFlags |= SYNC_PRIVATE; |
| 159 | if( find_option("once",0,0)!=0) urlFlags &= ~URL_REMEMBER; |
| @@ -189,10 +192,16 @@ | |
| 192 | } |
| 193 | fossil_free(zBase); |
| 194 | } |
| 195 | if( -1 != file_size(zRepo, ExtFILE) ){ |
| 196 | fossil_fatal("file already exists: %s", zRepo); |
| 197 | } |
| 198 | /* Fail before clone if open will fail because inside an open checkout */ |
| 199 | if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ |
| 200 | if( db_open_local_v2(0, allowNested) ){ |
| 201 | fossil_fatal("there is already an open tree at %s", g.zLocalRoot); |
| 202 | } |
| 203 | } |
| 204 | url_parse(g.argv[2], urlFlags); |
| 205 | if( zDefaultUser==0 && g.url.user!=0 ) zDefaultUser = g.url.user; |
| 206 | if( g.url.isFile ){ |
| 207 | file_copy(g.url.name, zRepo); |
| @@ -277,22 +286,29 @@ | |
| 286 | fossil_print("\nproject-id: %s\n", db_get("project-code", 0)); |
| 287 | fossil_print("server-id: %s\n", db_get("server-code", 0)); |
| 288 | zPassword = db_text(0, "SELECT pw FROM user WHERE login=%Q", g.zLogin); |
| 289 | fossil_print("admin-user: %s (password is \"%s\")\n", g.zLogin, zPassword); |
| 290 | if( zWorkDir!=0 && zWorkDir[0]!=0 && !noOpen ){ |
| 291 | char *azNew[7]; |
| 292 | int nargs = 5; |
| 293 | fossil_print("opening the new %s repository in directory %s...\n", |
| 294 | zRepo, zWorkDir); |
| 295 | azNew[0] = g.argv[0]; |
| 296 | azNew[1] = "open"; |
| 297 | azNew[2] = (char*)zRepo; |
| 298 | azNew[3] = "--workdir"; |
| 299 | azNew[4] = (char*)zWorkDir; |
| 300 | if( allowNested ){ |
| 301 | azNew[5] = "--nested"; |
| 302 | nargs++; |
| 303 | }else{ |
| 304 | azNew[5] = 0; |
| 305 | } |
| 306 | azNew[6] = 0; |
| 307 | g.argv = azNew; |
| 308 | g.argc = nargs; |
| 309 | cmd_open(); |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | /* |
| 314 | ** If user chooses to use HTTP Authentication over unencrypted HTTP, |
| 315 |
+4
| --- src/extcgi.c | ||
| +++ src/extcgi.c | ||
| @@ -67,10 +67,11 @@ | ||
| 67 | 67 | "PATH_INFO", |
| 68 | 68 | "QUERY_STRING", |
| 69 | 69 | "REMOTE_ADDR", |
| 70 | 70 | "REMOTE_USER", |
| 71 | 71 | "REQUEST_METHOD", |
| 72 | + "REQUEST_SCHEME", | |
| 72 | 73 | "REQUEST_URI", |
| 73 | 74 | "SCRIPT_DIRECTORY", |
| 74 | 75 | "SCRIPT_FILENAME", |
| 75 | 76 | "SCRIPT_NAME", |
| 76 | 77 | "SERVER_NAME", |
| @@ -326,10 +327,13 @@ | ||
| 326 | 327 | }else if( fossil_strnicmp(zLine,"Content-Type:",13)==0 ){ |
| 327 | 328 | int j; |
| 328 | 329 | for(i=13; fossil_isspace(zLine[i]); i++){} |
| 329 | 330 | for(j=i; zLine[j] && zLine[j]!=';'; j++){} |
| 330 | 331 | zMime = mprintf("%.*s", j-i, &zLine[i]); |
| 332 | + }else{ | |
| 333 | + cgi_append_header(zLine); | |
| 334 | + cgi_append_header("\r\n"); | |
| 331 | 335 | } |
| 332 | 336 | } |
| 333 | 337 | } |
| 334 | 338 | blob_read_from_channel(&reply, fromChild, nContent); |
| 335 | 339 | zFailReason = 0; /* Indicate success */ |
| 336 | 340 |
| --- src/extcgi.c | |
| +++ src/extcgi.c | |
| @@ -67,10 +67,11 @@ | |
| 67 | "PATH_INFO", |
| 68 | "QUERY_STRING", |
| 69 | "REMOTE_ADDR", |
| 70 | "REMOTE_USER", |
| 71 | "REQUEST_METHOD", |
| 72 | "REQUEST_URI", |
| 73 | "SCRIPT_DIRECTORY", |
| 74 | "SCRIPT_FILENAME", |
| 75 | "SCRIPT_NAME", |
| 76 | "SERVER_NAME", |
| @@ -326,10 +327,13 @@ | |
| 326 | }else if( fossil_strnicmp(zLine,"Content-Type:",13)==0 ){ |
| 327 | int j; |
| 328 | for(i=13; fossil_isspace(zLine[i]); i++){} |
| 329 | for(j=i; zLine[j] && zLine[j]!=';'; j++){} |
| 330 | zMime = mprintf("%.*s", j-i, &zLine[i]); |
| 331 | } |
| 332 | } |
| 333 | } |
| 334 | blob_read_from_channel(&reply, fromChild, nContent); |
| 335 | zFailReason = 0; /* Indicate success */ |
| 336 |
| --- src/extcgi.c | |
| +++ src/extcgi.c | |
| @@ -67,10 +67,11 @@ | |
| 67 | "PATH_INFO", |
| 68 | "QUERY_STRING", |
| 69 | "REMOTE_ADDR", |
| 70 | "REMOTE_USER", |
| 71 | "REQUEST_METHOD", |
| 72 | "REQUEST_SCHEME", |
| 73 | "REQUEST_URI", |
| 74 | "SCRIPT_DIRECTORY", |
| 75 | "SCRIPT_FILENAME", |
| 76 | "SCRIPT_NAME", |
| 77 | "SERVER_NAME", |
| @@ -326,10 +327,13 @@ | |
| 327 | }else if( fossil_strnicmp(zLine,"Content-Type:",13)==0 ){ |
| 328 | int j; |
| 329 | for(i=13; fossil_isspace(zLine[i]); i++){} |
| 330 | for(j=i; zLine[j] && zLine[j]!=';'; j++){} |
| 331 | zMime = mprintf("%.*s", j-i, &zLine[i]); |
| 332 | }else{ |
| 333 | cgi_append_header(zLine); |
| 334 | cgi_append_header("\r\n"); |
| 335 | } |
| 336 | } |
| 337 | } |
| 338 | blob_read_from_channel(&reply, fromChild, nContent); |
| 339 | zFailReason = 0; /* Indicate success */ |
| 340 |
+16
-11
| --- src/fossil.fetch.js | ||
| +++ src/fossil.fetch.js | ||
| @@ -70,18 +70,20 @@ | ||
| 70 | 70 | header values. When a map is passed on, all of its keys are |
| 71 | 71 | lower-cased. When a given header is requested and that header is |
| 72 | 72 | set multiple times, their values are (per the XHR docs) |
| 73 | 73 | concatenated together with ", " between them. |
| 74 | 74 | |
| 75 | - - beforesend/aftersend: optional callbacks which are called without | |
| 76 | - arguments immediately before the request is submitted and | |
| 77 | - immediately after it is received, regardless of success or | |
| 78 | - error. In the context of the callback, the options object is the | |
| 79 | - "this". These can be used to, e.g., keep track of in-flight | |
| 80 | - requests and update the UI accordingly, e.g. disabling/enabling DOM | |
| 81 | - elements. Any exceptions triggered by beforesend/aftersend are | |
| 82 | - caught and silently ignored. | |
| 75 | + - beforesend/aftersend: optional callbacks which are called | |
| 76 | + without arguments immediately before the request is submitted | |
| 77 | + and immediately after it is received, regardless of success or | |
| 78 | + error. In the context of the callback, the options object is | |
| 79 | + the "this". These can be used to, e.g., keep track of in-flight | |
| 80 | + requests and update the UI accordingly, e.g. disabling/enabling | |
| 81 | + DOM elements. Any exceptions thrown in an beforesend are passed | |
| 82 | + to the onerror() handler and cause the fetch() to prematurely | |
| 83 | + abort. Exceptions thrown in aftersend are currently silently | |
| 84 | + ignored (feature or bug?). | |
| 83 | 85 | |
| 84 | 86 | - timeout: integer in milliseconds specifying the XHR timeout |
| 85 | 87 | duration. Default = fossil.fetch.timeout. |
| 86 | 88 | |
| 87 | 89 | When an options object does not provide |
| @@ -91,12 +93,11 @@ | ||
| 91 | 93 | default onload/onerror implementations route the data through the |
| 92 | 94 | dev console and (for onerror()) through fossil.error(). The default |
| 93 | 95 | beforesend/aftersend are no-ops. Individual pages may overwrite |
| 94 | 96 | those members to provide default implementations suitable for the |
| 95 | 97 | page's use, e.g. keeping track of how many in-flight ajax requests |
| 96 | - are pending. Any exceptions thrown in an beforesend/aftersend | |
| 97 | - handler are current ignored (feature or bug?). | |
| 98 | + are pending. | |
| 98 | 99 | |
| 99 | 100 | Note that this routine may add properties to the 2nd argument, so |
| 100 | 101 | that instance should not be kept around for later use. |
| 101 | 102 | |
| 102 | 103 | Returns this object, noting that the XHR request is asynchronous, |
| @@ -195,11 +196,15 @@ | ||
| 195 | 196 | opt.onload.apply(opt, args); |
| 196 | 197 | }catch(e){ |
| 197 | 198 | opt.onerror(e); |
| 198 | 199 | } |
| 199 | 200 | }; |
| 200 | - try{opt.beforesend()}catch(e){/*ignore*/} | |
| 201 | + try{opt.beforesend()} | |
| 202 | + catch(e){ | |
| 203 | + opt.onerror(e); | |
| 204 | + return; | |
| 205 | + } | |
| 201 | 206 | x.open(opt.method||'GET', url.join(''), true); |
| 202 | 207 | if('POST'===opt.method && 'string'===typeof opt.contentType){ |
| 203 | 208 | x.setRequestHeader('Content-Type',opt.contentType); |
| 204 | 209 | } |
| 205 | 210 | x.timeout = +opt.timeout || f.timeout; |
| 206 | 211 |
| --- src/fossil.fetch.js | |
| +++ src/fossil.fetch.js | |
| @@ -70,18 +70,20 @@ | |
| 70 | header values. When a map is passed on, all of its keys are |
| 71 | lower-cased. When a given header is requested and that header is |
| 72 | set multiple times, their values are (per the XHR docs) |
| 73 | concatenated together with ", " between them. |
| 74 | |
| 75 | - beforesend/aftersend: optional callbacks which are called without |
| 76 | arguments immediately before the request is submitted and |
| 77 | immediately after it is received, regardless of success or |
| 78 | error. In the context of the callback, the options object is the |
| 79 | "this". These can be used to, e.g., keep track of in-flight |
| 80 | requests and update the UI accordingly, e.g. disabling/enabling DOM |
| 81 | elements. Any exceptions triggered by beforesend/aftersend are |
| 82 | caught and silently ignored. |
| 83 | |
| 84 | - timeout: integer in milliseconds specifying the XHR timeout |
| 85 | duration. Default = fossil.fetch.timeout. |
| 86 | |
| 87 | When an options object does not provide |
| @@ -91,12 +93,11 @@ | |
| 91 | default onload/onerror implementations route the data through the |
| 92 | dev console and (for onerror()) through fossil.error(). The default |
| 93 | beforesend/aftersend are no-ops. Individual pages may overwrite |
| 94 | those members to provide default implementations suitable for the |
| 95 | page's use, e.g. keeping track of how many in-flight ajax requests |
| 96 | are pending. Any exceptions thrown in an beforesend/aftersend |
| 97 | handler are current ignored (feature or bug?). |
| 98 | |
| 99 | Note that this routine may add properties to the 2nd argument, so |
| 100 | that instance should not be kept around for later use. |
| 101 | |
| 102 | Returns this object, noting that the XHR request is asynchronous, |
| @@ -195,11 +196,15 @@ | |
| 195 | opt.onload.apply(opt, args); |
| 196 | }catch(e){ |
| 197 | opt.onerror(e); |
| 198 | } |
| 199 | }; |
| 200 | try{opt.beforesend()}catch(e){/*ignore*/} |
| 201 | x.open(opt.method||'GET', url.join(''), true); |
| 202 | if('POST'===opt.method && 'string'===typeof opt.contentType){ |
| 203 | x.setRequestHeader('Content-Type',opt.contentType); |
| 204 | } |
| 205 | x.timeout = +opt.timeout || f.timeout; |
| 206 |
| --- src/fossil.fetch.js | |
| +++ src/fossil.fetch.js | |
| @@ -70,18 +70,20 @@ | |
| 70 | header values. When a map is passed on, all of its keys are |
| 71 | lower-cased. When a given header is requested and that header is |
| 72 | set multiple times, their values are (per the XHR docs) |
| 73 | concatenated together with ", " between them. |
| 74 | |
| 75 | - beforesend/aftersend: optional callbacks which are called |
| 76 | without arguments immediately before the request is submitted |
| 77 | and immediately after it is received, regardless of success or |
| 78 | error. In the context of the callback, the options object is |
| 79 | the "this". These can be used to, e.g., keep track of in-flight |
| 80 | requests and update the UI accordingly, e.g. disabling/enabling |
| 81 | DOM elements. Any exceptions thrown in an beforesend are passed |
| 82 | to the onerror() handler and cause the fetch() to prematurely |
| 83 | abort. Exceptions thrown in aftersend are currently silently |
| 84 | ignored (feature or bug?). |
| 85 | |
| 86 | - timeout: integer in milliseconds specifying the XHR timeout |
| 87 | duration. Default = fossil.fetch.timeout. |
| 88 | |
| 89 | When an options object does not provide |
| @@ -91,12 +93,11 @@ | |
| 93 | default onload/onerror implementations route the data through the |
| 94 | dev console and (for onerror()) through fossil.error(). The default |
| 95 | beforesend/aftersend are no-ops. Individual pages may overwrite |
| 96 | those members to provide default implementations suitable for the |
| 97 | page's use, e.g. keeping track of how many in-flight ajax requests |
| 98 | are pending. |
| 99 | |
| 100 | Note that this routine may add properties to the 2nd argument, so |
| 101 | that instance should not be kept around for later use. |
| 102 | |
| 103 | Returns this object, noting that the XHR request is asynchronous, |
| @@ -195,11 +196,15 @@ | |
| 196 | opt.onload.apply(opt, args); |
| 197 | }catch(e){ |
| 198 | opt.onerror(e); |
| 199 | } |
| 200 | }; |
| 201 | try{opt.beforesend()} |
| 202 | catch(e){ |
| 203 | opt.onerror(e); |
| 204 | return; |
| 205 | } |
| 206 | x.open(opt.method||'GET', url.join(''), true); |
| 207 | if('POST'===opt.method && 'string'===typeof opt.contentType){ |
| 208 | x.setRequestHeader('Content-Type',opt.contentType); |
| 209 | } |
| 210 | x.timeout = +opt.timeout || f.timeout; |
| 211 |
+6
-2
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -1424,16 +1424,20 @@ | ||
| 1424 | 1424 | }else |
| 1425 | 1425 | #endif /* FOSSIL_ENABLE_JSON */ |
| 1426 | 1426 | { |
| 1427 | 1427 | const char *zUrl = PD("REQUEST_URI", "index"); |
| 1428 | 1428 | const char *zQS = P("QUERY_STRING"); |
| 1429 | + char *zUrlNoQS; | |
| 1430 | + int i; | |
| 1429 | 1431 | Blob redir; |
| 1430 | 1432 | blob_init(&redir, 0, 0); |
| 1433 | + for(i=0; zUrl[i] && zUrl[i]!='?'; i++){} | |
| 1434 | + zUrlNoQS = fossil_strndup(zUrl, i); | |
| 1431 | 1435 | if( fossil_wants_https(1) ){ |
| 1432 | - blob_appendf(&redir, "%s/login?g=%T", g.zHttpsURL, zUrl); | |
| 1436 | + blob_appendf(&redir, "%s/login?g=%T", g.zHttpsURL, zUrlNoQS); | |
| 1433 | 1437 | }else{ |
| 1434 | - blob_appendf(&redir, "%R/login?g=%T", zUrl); | |
| 1438 | + blob_appendf(&redir, "%R/login?g=%T", zUrlNoQS); | |
| 1435 | 1439 | } |
| 1436 | 1440 | if( zQS && zQS[0] ){ |
| 1437 | 1441 | blob_appendf(&redir, "%%3f%T", zQS); |
| 1438 | 1442 | } |
| 1439 | 1443 | if( anonOk ) blob_append(&redir, "&anon", 5); |
| 1440 | 1444 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -1424,16 +1424,20 @@ | |
| 1424 | }else |
| 1425 | #endif /* FOSSIL_ENABLE_JSON */ |
| 1426 | { |
| 1427 | const char *zUrl = PD("REQUEST_URI", "index"); |
| 1428 | const char *zQS = P("QUERY_STRING"); |
| 1429 | Blob redir; |
| 1430 | blob_init(&redir, 0, 0); |
| 1431 | if( fossil_wants_https(1) ){ |
| 1432 | blob_appendf(&redir, "%s/login?g=%T", g.zHttpsURL, zUrl); |
| 1433 | }else{ |
| 1434 | blob_appendf(&redir, "%R/login?g=%T", zUrl); |
| 1435 | } |
| 1436 | if( zQS && zQS[0] ){ |
| 1437 | blob_appendf(&redir, "%%3f%T", zQS); |
| 1438 | } |
| 1439 | if( anonOk ) blob_append(&redir, "&anon", 5); |
| 1440 |
| --- src/login.c | |
| +++ src/login.c | |
| @@ -1424,16 +1424,20 @@ | |
| 1424 | }else |
| 1425 | #endif /* FOSSIL_ENABLE_JSON */ |
| 1426 | { |
| 1427 | const char *zUrl = PD("REQUEST_URI", "index"); |
| 1428 | const char *zQS = P("QUERY_STRING"); |
| 1429 | char *zUrlNoQS; |
| 1430 | int i; |
| 1431 | Blob redir; |
| 1432 | blob_init(&redir, 0, 0); |
| 1433 | for(i=0; zUrl[i] && zUrl[i]!='?'; i++){} |
| 1434 | zUrlNoQS = fossil_strndup(zUrl, i); |
| 1435 | if( fossil_wants_https(1) ){ |
| 1436 | blob_appendf(&redir, "%s/login?g=%T", g.zHttpsURL, zUrlNoQS); |
| 1437 | }else{ |
| 1438 | blob_appendf(&redir, "%R/login?g=%T", zUrlNoQS); |
| 1439 | } |
| 1440 | if( zQS && zQS[0] ){ |
| 1441 | blob_appendf(&redir, "%%3f%T", zQS); |
| 1442 | } |
| 1443 | if( anonOk ) blob_append(&redir, "&anon", 5); |
| 1444 |
-1
| --- src/sqlcmd.c | ||
| +++ src/sqlcmd.c | ||
| @@ -119,11 +119,10 @@ | ||
| 119 | 119 | pIn = sqlite3_value_blob(argv[0]); |
| 120 | 120 | if( pIn==0 ) return; |
| 121 | 121 | nIn = sqlite3_value_bytes(argv[0]); |
| 122 | 122 | if( nIn<4 ) return; |
| 123 | 123 | nOut = (pIn[0]<<24) + (pIn[1]<<16) + (pIn[2]<<8) + pIn[3]; |
| 124 | - if( nOut<0 ) return; | |
| 125 | 124 | pOut = sqlite3_malloc( nOut+1 ); |
| 126 | 125 | rc = uncompress(pOut, &nOut, &pIn[4], nIn-4); |
| 127 | 126 | if( rc==Z_OK ){ |
| 128 | 127 | sqlite3_result_blob(context, pOut, nOut, sqlite3_free); |
| 129 | 128 | }else if( rc==Z_MEM_ERROR ){ |
| 130 | 129 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -119,11 +119,10 @@ | |
| 119 | pIn = sqlite3_value_blob(argv[0]); |
| 120 | if( pIn==0 ) return; |
| 121 | nIn = sqlite3_value_bytes(argv[0]); |
| 122 | if( nIn<4 ) return; |
| 123 | nOut = (pIn[0]<<24) + (pIn[1]<<16) + (pIn[2]<<8) + pIn[3]; |
| 124 | if( nOut<0 ) return; |
| 125 | pOut = sqlite3_malloc( nOut+1 ); |
| 126 | rc = uncompress(pOut, &nOut, &pIn[4], nIn-4); |
| 127 | if( rc==Z_OK ){ |
| 128 | sqlite3_result_blob(context, pOut, nOut, sqlite3_free); |
| 129 | }else if( rc==Z_MEM_ERROR ){ |
| 130 |
| --- src/sqlcmd.c | |
| +++ src/sqlcmd.c | |
| @@ -119,11 +119,10 @@ | |
| 119 | pIn = sqlite3_value_blob(argv[0]); |
| 120 | if( pIn==0 ) return; |
| 121 | nIn = sqlite3_value_bytes(argv[0]); |
| 122 | if( nIn<4 ) return; |
| 123 | nOut = (pIn[0]<<24) + (pIn[1]<<16) + (pIn[2]<<8) + pIn[3]; |
| 124 | pOut = sqlite3_malloc( nOut+1 ); |
| 125 | rc = uncompress(pOut, &nOut, &pIn[4], nIn-4); |
| 126 | if( rc==Z_OK ){ |
| 127 | sqlite3_result_blob(context, pOut, nOut, sqlite3_free); |
| 128 | }else if( rc==Z_MEM_ERROR ){ |
| 129 |
+4
-4
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -604,19 +604,19 @@ | ||
| 604 | 604 | ** comment on-the-fly |
| 605 | 605 | */ |
| 606 | 606 | wiki_hyperlink_override(zUuid); |
| 607 | 607 | if( zCom[0]=='-' ){ |
| 608 | 608 | @ Deleted wiki page "%z(href("%R/whistory?name=%t",zCom+1))\ |
| 609 | - @ %h(zCom+1)</a> | |
| 609 | + @ %h(zCom+1)</a>" | |
| 610 | 610 | }else if( (tmFlags & TIMELINE_REFS)!=0 |
| 611 | 611 | && (zCom[0]=='+' || zCom[0]==':') ){ |
| 612 | - @ Wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a> | |
| 612 | + @ Wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a>" | |
| 613 | 613 | }else if( zCom[0]=='+' ){ |
| 614 | - @ Added wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a> | |
| 614 | + @ Added wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a>" | |
| 615 | 615 | }else if( zCom[0]==':' ){ |
| 616 | 616 | @ Changes to wiki page "%z(href("%R/wiki?name=%t",zCom+1))\ |
| 617 | - @ %h(zCom+1)</a> | |
| 617 | + @ %h(zCom+1)</a>" | |
| 618 | 618 | }else{ |
| 619 | 619 | /* Legacy EVENT table entry that needs to be rebuilt */ |
| 620 | 620 | @ Changes to a wiki page → Obsolete EVENT table information. |
| 621 | 621 | @ Run "fossil rebuild" on the repository. |
| 622 | 622 | } |
| 623 | 623 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -604,19 +604,19 @@ | |
| 604 | ** comment on-the-fly |
| 605 | */ |
| 606 | wiki_hyperlink_override(zUuid); |
| 607 | if( zCom[0]=='-' ){ |
| 608 | @ Deleted wiki page "%z(href("%R/whistory?name=%t",zCom+1))\ |
| 609 | @ %h(zCom+1)</a> |
| 610 | }else if( (tmFlags & TIMELINE_REFS)!=0 |
| 611 | && (zCom[0]=='+' || zCom[0]==':') ){ |
| 612 | @ Wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a> |
| 613 | }else if( zCom[0]=='+' ){ |
| 614 | @ Added wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a> |
| 615 | }else if( zCom[0]==':' ){ |
| 616 | @ Changes to wiki page "%z(href("%R/wiki?name=%t",zCom+1))\ |
| 617 | @ %h(zCom+1)</a> |
| 618 | }else{ |
| 619 | /* Legacy EVENT table entry that needs to be rebuilt */ |
| 620 | @ Changes to a wiki page → Obsolete EVENT table information. |
| 621 | @ Run "fossil rebuild" on the repository. |
| 622 | } |
| 623 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -604,19 +604,19 @@ | |
| 604 | ** comment on-the-fly |
| 605 | */ |
| 606 | wiki_hyperlink_override(zUuid); |
| 607 | if( zCom[0]=='-' ){ |
| 608 | @ Deleted wiki page "%z(href("%R/whistory?name=%t",zCom+1))\ |
| 609 | @ %h(zCom+1)</a>" |
| 610 | }else if( (tmFlags & TIMELINE_REFS)!=0 |
| 611 | && (zCom[0]=='+' || zCom[0]==':') ){ |
| 612 | @ Wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a>" |
| 613 | }else if( zCom[0]=='+' ){ |
| 614 | @ Added wiki page "%z(href("%R/wiki?name=%t",zCom+1))%h(zCom+1)</a>" |
| 615 | }else if( zCom[0]==':' ){ |
| 616 | @ Changes to wiki page "%z(href("%R/wiki?name=%t",zCom+1))\ |
| 617 | @ %h(zCom+1)</a>" |
| 618 | }else{ |
| 619 | /* Legacy EVENT table entry that needs to be rebuilt */ |
| 620 | @ Changes to a wiki page → Obsolete EVENT table information. |
| 621 | @ Run "fossil rebuild" on the repository. |
| 622 | } |
| 623 |
+1
-1
| --- src/tktsetup.c | ||
| +++ src/tktsetup.c | ||
| @@ -364,11 +364,11 @@ | ||
| 364 | 364 | @ <td colspan="3"> |
| 365 | 365 | @ Enter a detailed description of the problem. |
| 366 | 366 | @ For code defects, be sure to provide details on exactly how |
| 367 | 367 | @ the problem can be reproduced. Provide as much detail as |
| 368 | 368 | @ possible. Format: |
| 369 | -@ <th1>combobox mutype {HTML {[links only]} Markdown {Plain Text} Wiki}} 1</th1> | |
| 369 | +@ <th1>combobox mutype {HTML {[links only]} Markdown {Plain Text} Wiki} 1</th1> | |
| 370 | 370 | @ <br /> |
| 371 | 371 | @ <th1>set nline [linecount $comment 50 10]</th1> |
| 372 | 372 | @ <textarea name="icomment" cols="80" rows="$nline" |
| 373 | 373 | @ wrap="virtual" class="wikiedit">$<icomment></textarea><br /> |
| 374 | 374 | @ </tr> |
| 375 | 375 |
| --- src/tktsetup.c | |
| +++ src/tktsetup.c | |
| @@ -364,11 +364,11 @@ | |
| 364 | @ <td colspan="3"> |
| 365 | @ Enter a detailed description of the problem. |
| 366 | @ For code defects, be sure to provide details on exactly how |
| 367 | @ the problem can be reproduced. Provide as much detail as |
| 368 | @ possible. Format: |
| 369 | @ <th1>combobox mutype {HTML {[links only]} Markdown {Plain Text} Wiki}} 1</th1> |
| 370 | @ <br /> |
| 371 | @ <th1>set nline [linecount $comment 50 10]</th1> |
| 372 | @ <textarea name="icomment" cols="80" rows="$nline" |
| 373 | @ wrap="virtual" class="wikiedit">$<icomment></textarea><br /> |
| 374 | @ </tr> |
| 375 |
| --- src/tktsetup.c | |
| +++ src/tktsetup.c | |
| @@ -364,11 +364,11 @@ | |
| 364 | @ <td colspan="3"> |
| 365 | @ Enter a detailed description of the problem. |
| 366 | @ For code defects, be sure to provide details on exactly how |
| 367 | @ the problem can be reproduced. Provide as much detail as |
| 368 | @ possible. Format: |
| 369 | @ <th1>combobox mutype {HTML {[links only]} Markdown {Plain Text} Wiki} 1</th1> |
| 370 | @ <br /> |
| 371 | @ <th1>set nline [linecount $comment 50 10]</th1> |
| 372 | @ <textarea name="icomment" cols="80" rows="$nline" |
| 373 | @ wrap="virtual" class="wikiedit">$<icomment></textarea><br /> |
| 374 | @ </tr> |
| 375 |
+3
-2
| --- www/backup.md | ||
| +++ www/backup.md | ||
| @@ -201,14 +201,15 @@ | ||
| 201 | 201 | of noise to anyone without the key: |
| 202 | 202 | |
| 203 | 203 | ---- |
| 204 | 204 | |
| 205 | 205 | ```shell |
| 206 | +iter=52830 | |
| 206 | 207 | pass="h8TixP6Mt6edJ3d6COaexiiFlvAM54auF2AjT7ZYYn" |
| 207 | 208 | gd="$HOME/Google Drive/Fossil Backups/$bf.xz.enc" |
| 208 | 209 | fossil sql -R ~/museum/backups/"$bf" .dump | xz -9 | |
| 209 | - openssl enc -e -aes-256-cbc -pbkdf2 -iter 52830 -pass pass:"$pass" -out "$gd" | |
| 210 | + openssl enc -e -aes-256-cbc -pbkdf2 -iter $iter -pass pass:"$pass" -out "$gd" | |
| 210 | 211 | ``` |
| 211 | 212 | |
| 212 | 213 | ---- |
| 213 | 214 | |
| 214 | 215 | If you’re adding this to the first script above, remove the |
| @@ -247,11 +248,11 @@ | ||
| 247 | 248 | it, but it’s worth showing it because there are some subtleties to take |
| 248 | 249 | care of. If all variables defined in earlier scripts are available, then |
| 249 | 250 | restoration is: |
| 250 | 251 | |
| 251 | 252 | ``` |
| 252 | -openssl enc -d -aes-256-cbc -pbkdf2 -iter 52830 -pass pass:"$pass" -in "$gd" | | |
| 253 | +openssl enc -d -aes-256-cbc -pbkdf2 -iter $iter -pass pass:"$pass" -in "$gd" | | |
| 253 | 254 | xz -d | fossil sql --no-repository ~/museum/restored-repo.fossil |
| 254 | 255 | ``` |
| 255 | 256 | |
| 256 | 257 | We changed the `-e` to `-d` on the `openssl` command to get decryption, |
| 257 | 258 | and we changed the `-out` to `-in` so it reads from the encrypted backup |
| 258 | 259 |
| --- www/backup.md | |
| +++ www/backup.md | |
| @@ -201,14 +201,15 @@ | |
| 201 | of noise to anyone without the key: |
| 202 | |
| 203 | ---- |
| 204 | |
| 205 | ```shell |
| 206 | pass="h8TixP6Mt6edJ3d6COaexiiFlvAM54auF2AjT7ZYYn" |
| 207 | gd="$HOME/Google Drive/Fossil Backups/$bf.xz.enc" |
| 208 | fossil sql -R ~/museum/backups/"$bf" .dump | xz -9 | |
| 209 | openssl enc -e -aes-256-cbc -pbkdf2 -iter 52830 -pass pass:"$pass" -out "$gd" |
| 210 | ``` |
| 211 | |
| 212 | ---- |
| 213 | |
| 214 | If you’re adding this to the first script above, remove the |
| @@ -247,11 +248,11 @@ | |
| 247 | it, but it’s worth showing it because there are some subtleties to take |
| 248 | care of. If all variables defined in earlier scripts are available, then |
| 249 | restoration is: |
| 250 | |
| 251 | ``` |
| 252 | openssl enc -d -aes-256-cbc -pbkdf2 -iter 52830 -pass pass:"$pass" -in "$gd" | |
| 253 | xz -d | fossil sql --no-repository ~/museum/restored-repo.fossil |
| 254 | ``` |
| 255 | |
| 256 | We changed the `-e` to `-d` on the `openssl` command to get decryption, |
| 257 | and we changed the `-out` to `-in` so it reads from the encrypted backup |
| 258 |
| --- www/backup.md | |
| +++ www/backup.md | |
| @@ -201,14 +201,15 @@ | |
| 201 | of noise to anyone without the key: |
| 202 | |
| 203 | ---- |
| 204 | |
| 205 | ```shell |
| 206 | iter=52830 |
| 207 | pass="h8TixP6Mt6edJ3d6COaexiiFlvAM54auF2AjT7ZYYn" |
| 208 | gd="$HOME/Google Drive/Fossil Backups/$bf.xz.enc" |
| 209 | fossil sql -R ~/museum/backups/"$bf" .dump | xz -9 | |
| 210 | openssl enc -e -aes-256-cbc -pbkdf2 -iter $iter -pass pass:"$pass" -out "$gd" |
| 211 | ``` |
| 212 | |
| 213 | ---- |
| 214 | |
| 215 | If you’re adding this to the first script above, remove the |
| @@ -247,11 +248,11 @@ | |
| 248 | it, but it’s worth showing it because there are some subtleties to take |
| 249 | care of. If all variables defined in earlier scripts are available, then |
| 250 | restoration is: |
| 251 | |
| 252 | ``` |
| 253 | openssl enc -d -aes-256-cbc -pbkdf2 -iter $iter -pass pass:"$pass" -in "$gd" | |
| 254 | xz -d | fossil sql --no-repository ~/museum/restored-repo.fossil |
| 255 | ``` |
| 256 | |
| 257 | We changed the `-e` to `-d` on the `openssl` command to get decryption, |
| 258 | and we changed the `-out` to `-in` so it reads from the encrypted backup |
| 259 |
+18
| --- www/changes.wiki | ||
| +++ www/changes.wiki | ||
| @@ -6,11 +6,29 @@ | ||
| 6 | 6 | * The "[/help?cmd=clone|fossil clone]" command is enhanced so that |
| 7 | 7 | if the repository filename is omitted, an appropriate name is derived |
| 8 | 8 | from the remote URL and the newly cloned repo is opened. This makes |
| 9 | 9 | the clone command work more like Git, thus making it easier for |
| 10 | 10 | people transitioning from Git. |
| 11 | + * Changed the way that wiki edits are stored in the EVENT table of the | |
| 12 | + database, for more flexibility and better features. | |
| 13 | + <b>Run "fossil rebuild" to take advantage of this change</b>. | |
| 11 | 14 | * Add the "contact" sub-command to [/help?cmd=user|fossil user]. |
| 15 | + * Added commands "[/help?cmd=all|fossil all git export]" and | |
| 16 | + "[/help?cmd=all|fossil all git status]". | |
| 17 | + * Improvements to the "[/sitemap]" page. Add subpages | |
| 18 | + [/sitemap-timeline] and [/sitemap-test]. | |
| 19 | + * Better text position in cylinder objects of Pikchr diagrams. | |
| 20 | + * New "details.txt" settings available to custom skins to better control | |
| 21 | + the rendering of Pikchr diagrams: | |
| 22 | + <ul> | |
| 23 | + <li> pikchr-foreground | |
| 24 | + <li> pikchr-scale | |
| 25 | + <li> pikchr-fontscale | |
| 26 | + </ul> | |
| 27 | + * Allow the use of SQL functions inside the ticket table definition | |
| 28 | + for custom ticket configurations. | |
| 29 | + * Countless improvements and enhancements to the documentation | |
| 12 | 30 | |
| 13 | 31 | <a name='v2_13'></a> |
| 14 | 32 | <h2>Changes for Version 2.13 (2020-11-01)</h2> |
| 15 | 33 | |
| 16 | 34 | * Added support for [./interwiki.md|interwiki links]. |
| 17 | 35 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -6,11 +6,29 @@ | |
| 6 | * The "[/help?cmd=clone|fossil clone]" command is enhanced so that |
| 7 | if the repository filename is omitted, an appropriate name is derived |
| 8 | from the remote URL and the newly cloned repo is opened. This makes |
| 9 | the clone command work more like Git, thus making it easier for |
| 10 | people transitioning from Git. |
| 11 | * Add the "contact" sub-command to [/help?cmd=user|fossil user]. |
| 12 | |
| 13 | <a name='v2_13'></a> |
| 14 | <h2>Changes for Version 2.13 (2020-11-01)</h2> |
| 15 | |
| 16 | * Added support for [./interwiki.md|interwiki links]. |
| 17 |
| --- www/changes.wiki | |
| +++ www/changes.wiki | |
| @@ -6,11 +6,29 @@ | |
| 6 | * The "[/help?cmd=clone|fossil clone]" command is enhanced so that |
| 7 | if the repository filename is omitted, an appropriate name is derived |
| 8 | from the remote URL and the newly cloned repo is opened. This makes |
| 9 | the clone command work more like Git, thus making it easier for |
| 10 | people transitioning from Git. |
| 11 | * Changed the way that wiki edits are stored in the EVENT table of the |
| 12 | database, for more flexibility and better features. |
| 13 | <b>Run "fossil rebuild" to take advantage of this change</b>. |
| 14 | * Add the "contact" sub-command to [/help?cmd=user|fossil user]. |
| 15 | * Added commands "[/help?cmd=all|fossil all git export]" and |
| 16 | "[/help?cmd=all|fossil all git status]". |
| 17 | * Improvements to the "[/sitemap]" page. Add subpages |
| 18 | [/sitemap-timeline] and [/sitemap-test]. |
| 19 | * Better text position in cylinder objects of Pikchr diagrams. |
| 20 | * New "details.txt" settings available to custom skins to better control |
| 21 | the rendering of Pikchr diagrams: |
| 22 | <ul> |
| 23 | <li> pikchr-foreground |
| 24 | <li> pikchr-scale |
| 25 | <li> pikchr-fontscale |
| 26 | </ul> |
| 27 | * Allow the use of SQL functions inside the ticket table definition |
| 28 | for custom ticket configurations. |
| 29 | * Countless improvements and enhancements to the documentation |
| 30 | |
| 31 | <a name='v2_13'></a> |
| 32 | <h2>Changes for Version 2.13 (2020-11-01)</h2> |
| 33 | |
| 34 | * Added support for [./interwiki.md|interwiki links]. |
| 35 |
+26
-38
| --- www/ckout-workflows.md | ||
| +++ www/ckout-workflows.md | ||
| @@ -2,12 +2,11 @@ | ||
| 2 | 2 | |
| 3 | 3 | Because Fossil separates the concept of “check-out directory” from |
| 4 | 4 | “repository DB file,” it gives you the freedom to choose from several |
| 5 | 5 | working styles. Contrast Git, where the two concepts are normally |
| 6 | 6 | intermingled in a single working directory, which strongly encourages |
| 7 | -the “update in place” working style, leaving its `git-worktree` feature | |
| 8 | -underutilized. | |
| 7 | +the “update in place” working style. | |
| 9 | 8 | |
| 10 | 9 | |
| 11 | 10 | ## <a id="mcw"></a> Multiple-Checkout Workflow |
| 12 | 11 | |
| 13 | 12 | With Fossil, it is routine to have multiple check-outs from the same |
| @@ -48,13 +47,13 @@ | ||
| 48 | 47 | |
| 49 | 48 | Each check-out operates independently of the others. |
| 50 | 49 | |
| 51 | 50 | This multiple-checkouts working style is especially useful when Fossil stores source code in programming languages |
| 52 | 51 | where there is a “build” step that transforms source files into files |
| 53 | -you actually run or distribute. With Git’s typical switch-in-place workflow, | |
| 54 | -you have to rebuild all outputs from the source files | |
| 55 | -that differ between those versions whenever you switch versions. In the above Fossil working model, | |
| 52 | +you actually run or distribute. Contrast a switch-in-place workflow, | |
| 53 | +where you have to rebuild all outputs from the source files | |
| 54 | +that differ between those versions whenever you switch versions. In the above model, | |
| 56 | 55 | you switch versions with a “`cd`” command instead, so that you only have |
| 57 | 56 | to rebuild outputs from files you yourself change. |
| 58 | 57 | |
| 59 | 58 | This style is also useful when a check-out directory may be tied up with |
| 60 | 59 | some long-running process, as with the “test” example above, where you |
| @@ -72,13 +71,13 @@ | ||
| 72 | 71 | Nevertheless, it is possible to work in a more typical Git sort of |
| 73 | 72 | style, switching between versions in a single check-out directory. |
| 74 | 73 | |
| 75 | 74 | #### <a id="idiomatic"></a> The Idiomatic Fossil Way |
| 76 | 75 | |
| 77 | -With the clone done as in [the prior section](#mdw), the most idiomatic | |
| 78 | -way is as follows: | |
| 76 | +The most idiomatic way is as follows: | |
| 79 | 77 | |
| 78 | + fossil clone https://example.com/repo /path/to/repo.fossil | |
| 80 | 79 | mkdir work-dir |
| 81 | 80 | cd work-dir |
| 82 | 81 | fossil open /path/to/repo.fossil |
| 83 | 82 | ...work on trunk... |
| 84 | 83 | |
| @@ -87,56 +86,44 @@ | ||
| 87 | 86 | |
| 88 | 87 | Basically, you replace the `cd` commands in the multiple checkouts |
| 89 | 88 | workflow above with `fossil up` commands. |
| 90 | 89 | |
| 91 | 90 | |
| 92 | -#### <a id="open"></a> The Clone-and-Open Way | |
| 91 | +#### <a id="open"></a> Opening a Repository by URI | |
| 93 | 92 | |
| 94 | -In Fossil 2.12, we added a feature that allows you to get closer to | |
| 95 | -Git’s single-step clone-and-open behavior: | |
| 93 | +In Fossil 2.12, we added a feature to simplify the single-worktree use | |
| 94 | +case: | |
| 96 | 95 | |
| 97 | 96 | mkdir work-dir |
| 98 | 97 | cd work-dir |
| 99 | 98 | fossil open https://example.com/repo |
| 100 | 99 | |
| 101 | 100 | Now you have “trunk” open in `work-dir`, with the repo file stored as |
| 102 | 101 | `repo.fossil` in that same directory. |
| 103 | 102 | |
| 104 | -The use of [`fossil open`][open] here instead of [`fossil clone`][clone] | |
| 105 | -is likely to surprise a Git user. When we were [discussing][caod] | |
| 106 | -this, we considered following the Git command style, but we decided | |
| 107 | -against it because it goes against this core Fossil design principle: | |
| 108 | -given that the Fossil repo is separate from the check-out, why would you | |
| 109 | -expect asking for a repo clone to also create a check-out directory for | |
| 110 | -you? We view commingled repository + check-out as a design error in | |
| 111 | -Git, so why would we repeat the error? | |
| 112 | - | |
| 113 | -To see why we see this behavior is error-prone, consider that | |
| 114 | -`git clean` must have an exception to avoid nuking the `.git` directory. | |
| 115 | -We had to add that complication to `fossil clean` when we added the | |
| 116 | -`fossil open URI` feature: it won’t nuke the repo DB file. | |
| 117 | - | |
| 118 | -[clone]: /help?cmd=clone | |
| 119 | -[open]: /help?cmd=open | |
| 120 | - | |
| 121 | - | |
| 122 | -#### <a id="clone"></a> The Git Clone Way | |
| 123 | - | |
| 124 | -This feature didn’t placate many Git fans, though, so with Fossil 2.14 — | |
| 125 | -currently unreleased — we now allow this: | |
| 103 | +Users of Git may be surprised that it doesn’t create a directory for you | |
| 104 | +and that you `cd` into it *before* the clone-and-open step, not after. | |
| 105 | +This is because we’re overloading the “open” command, which already had | |
| 106 | +the behavior of opening into the current working directory. Changing it | |
| 107 | +to behave like `git clone` would therefore make the behavior surprising | |
| 108 | +to Fossil users. (See [our discussions][caod] if you want the full | |
| 109 | +details.) | |
| 110 | + | |
| 111 | + | |
| 112 | +#### <a id="clone"></a> Git-Like Clone-and-Open | |
| 113 | + | |
| 114 | +With Fossil 2.14 — currently unreleased — we added a more Git-like | |
| 115 | +alternative: | |
| 126 | 116 | |
| 127 | 117 | fossil clone https://fossil-scm.org/fossil |
| 118 | + cd fossil | |
| 128 | 119 | |
| 129 | 120 | This results in a `fossil.fossil` repo DB file and a `fossil/` working |
| 130 | 121 | directory. |
| 131 | 122 | |
| 132 | 123 | Note that our `clone URI` behavior does not commingle the repo and |
| 133 | -check-out, solving our major problem with the Git design, though we | |
| 134 | -still believe it to be confusing to have “clone” be part of “open,” and | |
| 135 | -still more confusing to have “open” part of “clone.” We prefer keeping | |
| 136 | -these operations entirely separate, either as at the [top of this | |
| 137 | -section](#scw) or [as in the prior one](#mcw). Still, please yourself. | |
| 124 | +check-out, solving our major problem with the Git design. | |
| 138 | 125 | |
| 139 | 126 | If you want the repo to be named something else, adjust the URL: |
| 140 | 127 | |
| 141 | 128 | fossil clone https://fossil-scm.org/fossil/fsl |
| 142 | 129 | |
| @@ -149,8 +136,9 @@ | ||
| 149 | 136 | fossil clone https://dev.example.com/repo/my-project |
| 150 | 137 | |
| 151 | 138 | The `/repo` addition is the key: whatever comes after is used as the |
| 152 | 139 | repository name. [See the docs][clone] for more details. |
| 153 | 140 | |
| 154 | -[caod]: https://fossil-scm.org/forum/forumpost/3f143cec74 | |
| 141 | +[caod]: https://fossil-scm.org/forum/forumpost/3f143cec74 | |
| 142 | +[clone]: /help?cmd=clone | |
| 155 | 143 | |
| 156 | 144 | <div style="height:50em" id="this-space-intentionally-left-blank"></div> |
| 157 | 145 |
| --- www/ckout-workflows.md | |
| +++ www/ckout-workflows.md | |
| @@ -2,12 +2,11 @@ | |
| 2 | |
| 3 | Because Fossil separates the concept of “check-out directory” from |
| 4 | “repository DB file,” it gives you the freedom to choose from several |
| 5 | working styles. Contrast Git, where the two concepts are normally |
| 6 | intermingled in a single working directory, which strongly encourages |
| 7 | the “update in place” working style, leaving its `git-worktree` feature |
| 8 | underutilized. |
| 9 | |
| 10 | |
| 11 | ## <a id="mcw"></a> Multiple-Checkout Workflow |
| 12 | |
| 13 | With Fossil, it is routine to have multiple check-outs from the same |
| @@ -48,13 +47,13 @@ | |
| 48 | |
| 49 | Each check-out operates independently of the others. |
| 50 | |
| 51 | This multiple-checkouts working style is especially useful when Fossil stores source code in programming languages |
| 52 | where there is a “build” step that transforms source files into files |
| 53 | you actually run or distribute. With Git’s typical switch-in-place workflow, |
| 54 | you have to rebuild all outputs from the source files |
| 55 | that differ between those versions whenever you switch versions. In the above Fossil working model, |
| 56 | you switch versions with a “`cd`” command instead, so that you only have |
| 57 | to rebuild outputs from files you yourself change. |
| 58 | |
| 59 | This style is also useful when a check-out directory may be tied up with |
| 60 | some long-running process, as with the “test” example above, where you |
| @@ -72,13 +71,13 @@ | |
| 72 | Nevertheless, it is possible to work in a more typical Git sort of |
| 73 | style, switching between versions in a single check-out directory. |
| 74 | |
| 75 | #### <a id="idiomatic"></a> The Idiomatic Fossil Way |
| 76 | |
| 77 | With the clone done as in [the prior section](#mdw), the most idiomatic |
| 78 | way is as follows: |
| 79 | |
| 80 | mkdir work-dir |
| 81 | cd work-dir |
| 82 | fossil open /path/to/repo.fossil |
| 83 | ...work on trunk... |
| 84 | |
| @@ -87,56 +86,44 @@ | |
| 87 | |
| 88 | Basically, you replace the `cd` commands in the multiple checkouts |
| 89 | workflow above with `fossil up` commands. |
| 90 | |
| 91 | |
| 92 | #### <a id="open"></a> The Clone-and-Open Way |
| 93 | |
| 94 | In Fossil 2.12, we added a feature that allows you to get closer to |
| 95 | Git’s single-step clone-and-open behavior: |
| 96 | |
| 97 | mkdir work-dir |
| 98 | cd work-dir |
| 99 | fossil open https://example.com/repo |
| 100 | |
| 101 | Now you have “trunk” open in `work-dir`, with the repo file stored as |
| 102 | `repo.fossil` in that same directory. |
| 103 | |
| 104 | The use of [`fossil open`][open] here instead of [`fossil clone`][clone] |
| 105 | is likely to surprise a Git user. When we were [discussing][caod] |
| 106 | this, we considered following the Git command style, but we decided |
| 107 | against it because it goes against this core Fossil design principle: |
| 108 | given that the Fossil repo is separate from the check-out, why would you |
| 109 | expect asking for a repo clone to also create a check-out directory for |
| 110 | you? We view commingled repository + check-out as a design error in |
| 111 | Git, so why would we repeat the error? |
| 112 | |
| 113 | To see why we see this behavior is error-prone, consider that |
| 114 | `git clean` must have an exception to avoid nuking the `.git` directory. |
| 115 | We had to add that complication to `fossil clean` when we added the |
| 116 | `fossil open URI` feature: it won’t nuke the repo DB file. |
| 117 | |
| 118 | [clone]: /help?cmd=clone |
| 119 | [open]: /help?cmd=open |
| 120 | |
| 121 | |
| 122 | #### <a id="clone"></a> The Git Clone Way |
| 123 | |
| 124 | This feature didn’t placate many Git fans, though, so with Fossil 2.14 — |
| 125 | currently unreleased — we now allow this: |
| 126 | |
| 127 | fossil clone https://fossil-scm.org/fossil |
| 128 | |
| 129 | This results in a `fossil.fossil` repo DB file and a `fossil/` working |
| 130 | directory. |
| 131 | |
| 132 | Note that our `clone URI` behavior does not commingle the repo and |
| 133 | check-out, solving our major problem with the Git design, though we |
| 134 | still believe it to be confusing to have “clone” be part of “open,” and |
| 135 | still more confusing to have “open” part of “clone.” We prefer keeping |
| 136 | these operations entirely separate, either as at the [top of this |
| 137 | section](#scw) or [as in the prior one](#mcw). Still, please yourself. |
| 138 | |
| 139 | If you want the repo to be named something else, adjust the URL: |
| 140 | |
| 141 | fossil clone https://fossil-scm.org/fossil/fsl |
| 142 | |
| @@ -149,8 +136,9 @@ | |
| 149 | fossil clone https://dev.example.com/repo/my-project |
| 150 | |
| 151 | The `/repo` addition is the key: whatever comes after is used as the |
| 152 | repository name. [See the docs][clone] for more details. |
| 153 | |
| 154 | [caod]: https://fossil-scm.org/forum/forumpost/3f143cec74 |
| 155 | |
| 156 | <div style="height:50em" id="this-space-intentionally-left-blank"></div> |
| 157 |
| --- www/ckout-workflows.md | |
| +++ www/ckout-workflows.md | |
| @@ -2,12 +2,11 @@ | |
| 2 | |
| 3 | Because Fossil separates the concept of “check-out directory” from |
| 4 | “repository DB file,” it gives you the freedom to choose from several |
| 5 | working styles. Contrast Git, where the two concepts are normally |
| 6 | intermingled in a single working directory, which strongly encourages |
| 7 | the “update in place” working style. |
| 8 | |
| 9 | |
| 10 | ## <a id="mcw"></a> Multiple-Checkout Workflow |
| 11 | |
| 12 | With Fossil, it is routine to have multiple check-outs from the same |
| @@ -48,13 +47,13 @@ | |
| 47 | |
| 48 | Each check-out operates independently of the others. |
| 49 | |
| 50 | This multiple-checkouts working style is especially useful when Fossil stores source code in programming languages |
| 51 | where there is a “build” step that transforms source files into files |
| 52 | you actually run or distribute. Contrast a switch-in-place workflow, |
| 53 | where you have to rebuild all outputs from the source files |
| 54 | that differ between those versions whenever you switch versions. In the above model, |
| 55 | you switch versions with a “`cd`” command instead, so that you only have |
| 56 | to rebuild outputs from files you yourself change. |
| 57 | |
| 58 | This style is also useful when a check-out directory may be tied up with |
| 59 | some long-running process, as with the “test” example above, where you |
| @@ -72,13 +71,13 @@ | |
| 71 | Nevertheless, it is possible to work in a more typical Git sort of |
| 72 | style, switching between versions in a single check-out directory. |
| 73 | |
| 74 | #### <a id="idiomatic"></a> The Idiomatic Fossil Way |
| 75 | |
| 76 | The most idiomatic way is as follows: |
| 77 | |
| 78 | fossil clone https://example.com/repo /path/to/repo.fossil |
| 79 | mkdir work-dir |
| 80 | cd work-dir |
| 81 | fossil open /path/to/repo.fossil |
| 82 | ...work on trunk... |
| 83 | |
| @@ -87,56 +86,44 @@ | |
| 86 | |
| 87 | Basically, you replace the `cd` commands in the multiple checkouts |
| 88 | workflow above with `fossil up` commands. |
| 89 | |
| 90 | |
| 91 | #### <a id="open"></a> Opening a Repository by URI |
| 92 | |
| 93 | In Fossil 2.12, we added a feature to simplify the single-worktree use |
| 94 | case: |
| 95 | |
| 96 | mkdir work-dir |
| 97 | cd work-dir |
| 98 | fossil open https://example.com/repo |
| 99 | |
| 100 | Now you have “trunk” open in `work-dir`, with the repo file stored as |
| 101 | `repo.fossil` in that same directory. |
| 102 | |
| 103 | Users of Git may be surprised that it doesn’t create a directory for you |
| 104 | and that you `cd` into it *before* the clone-and-open step, not after. |
| 105 | This is because we’re overloading the “open” command, which already had |
| 106 | the behavior of opening into the current working directory. Changing it |
| 107 | to behave like `git clone` would therefore make the behavior surprising |
| 108 | to Fossil users. (See [our discussions][caod] if you want the full |
| 109 | details.) |
| 110 | |
| 111 | |
| 112 | #### <a id="clone"></a> Git-Like Clone-and-Open |
| 113 | |
| 114 | With Fossil 2.14 — currently unreleased — we added a more Git-like |
| 115 | alternative: |
| 116 | |
| 117 | fossil clone https://fossil-scm.org/fossil |
| 118 | cd fossil |
| 119 | |
| 120 | This results in a `fossil.fossil` repo DB file and a `fossil/` working |
| 121 | directory. |
| 122 | |
| 123 | Note that our `clone URI` behavior does not commingle the repo and |
| 124 | check-out, solving our major problem with the Git design. |
| 125 | |
| 126 | If you want the repo to be named something else, adjust the URL: |
| 127 | |
| 128 | fossil clone https://fossil-scm.org/fossil/fsl |
| 129 | |
| @@ -149,8 +136,9 @@ | |
| 136 | fossil clone https://dev.example.com/repo/my-project |
| 137 | |
| 138 | The `/repo` addition is the key: whatever comes after is used as the |
| 139 | repository name. [See the docs][clone] for more details. |
| 140 | |
| 141 | [caod]: https://fossil-scm.org/forum/forumpost/3f143cec74 |
| 142 | [clone]: /help?cmd=clone |
| 143 | |
| 144 | <div style="height:50em" id="this-space-intentionally-left-blank"></div> |
| 145 |
+90
-84
| --- www/fossil-v-git.wiki | ||
| +++ www/fossil-v-git.wiki | ||
| @@ -43,22 +43,22 @@ | ||
| 43 | 43 | <td>VCS, tickets, wiki, docs, notes, forum, UI, |
| 44 | 44 | [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td> |
| 45 | 45 | <td><a href="#features">2.1 ↓</a></td> |
| 46 | 46 | </tr> |
| 47 | 47 | <tr> |
| 48 | - <td>Sprawling and inefficient</td> | |
| 49 | - <td>Self-contained and efficient</td> | |
| 50 | - <td><a href="#efficient">2.2 ↓</a></td> | |
| 48 | + <td>A federation of many small programs</td> | |
| 49 | + <td>One self-contained, stand-alone executable</td> | |
| 50 | + <td><a href="#selfcontained">2.2 ↓</a></td> | |
| 51 | 51 | </tr> |
| 52 | 52 | <tr> |
| 53 | - <td>One-off custom pile-of-files data store</td> | |
| 54 | - <td>[https://sqlite.org/famous.html|The most popular database in the world]</td> | |
| 53 | + <td>Custom key/value data store</td> | |
| 54 | + <td>[https://sqlite.org/mostdeployed.html|The most used SQL database in the world]</td> | |
| 55 | 55 | <td><a href="#durable">2.3 ↓</a></td> |
| 56 | 56 | </tr> |
| 57 | 57 | <tr> |
| 58 | - <td>Runs natively on POSIX systems only</td> | |
| 59 | - <td>Native on common desktop & server platforms</td> | |
| 58 | + <td>Runs natively on POSIX systems</td> | |
| 59 | + <td>Runs natively on both POSIX and Windows</td> | |
| 60 | 60 | <td><a href="#portable">2.4 ↓</a></td> |
| 61 | 61 | </tr> |
| 62 | 62 | <tr> |
| 63 | 63 | <td>Bazaar-style development</td> |
| 64 | 64 | <td>Cathedral-style development</td> |
| @@ -93,12 +93,12 @@ | ||
| 93 | 93 | <td>Commit first</td> |
| 94 | 94 | <td>Test first</td> |
| 95 | 95 | <td><a href="#testing">2.8 ↓</a></td> |
| 96 | 96 | </tr> |
| 97 | 97 | <tr> |
| 98 | - <td>SHA-2</td> | |
| 99 | - <td>SHA-3</td> | |
| 98 | + <td>SHA-1 or SHA-2</td> | |
| 99 | + <td>SHA-1 and/or SHA-3, in the same repository</td> | |
| 100 | 100 | <td><a href="#hash">2.9 ↓</a></td> |
| 101 | 101 | </tr> |
| 102 | 102 | </table></blockquote> |
| 103 | 103 | |
| 104 | 104 | <h3 id="features">2.1 Featureful</h3> |
| @@ -117,16 +117,16 @@ | ||
| 117 | 117 | the design. One way to describe Fossil is that it is |
| 118 | 118 | "[https://github.com/ | GitHub]-in-a-box." |
| 119 | 119 | |
| 120 | 120 | Fossil can do operations over all local repo clones and check-out |
| 121 | 121 | directories with a single command. For example, Fossil lets you say |
| 122 | -<tt>fossil all sync</tt> on a laptop prior to taking it off the network | |
| 122 | +"<tt>fossil all sync</tt>" on a laptop prior to taking it off the network | |
| 123 | 123 | hosting those repos. You can sync up to all of the private repos on your |
| 124 | 124 | company network plus those public Internet-hosted repos you use. Whether |
| 125 | 125 | going out for a working lunch or on a transoceanic airplane trip, one |
| 126 | 126 | command gets you in sync. This works with several other Fossil |
| 127 | -sub-commands, such as <tt>fossil all changes</tt> to get a list of files | |
| 127 | +sub-commands, such as "<tt>fossil all changes</tt>" to get a list of files | |
| 128 | 128 | that you forgot to commit prior to the end of your working day, across |
| 129 | 129 | all repos. |
| 130 | 130 | |
| 131 | 131 | Whenever Fossil is told to modify the local checkout in some destructive |
| 132 | 132 | way ([/help?cmd=rm|fossil rm], [/help?cmd=update|fossil update], |
| @@ -154,11 +154,11 @@ | ||
| 154 | 154 | history, and so forth.² That means you get a copy of this very article |
| 155 | 155 | and all of its historical versions, plus the same for all of the other |
| 156 | 156 | public content on this site. |
| 157 | 157 | |
| 158 | 158 | |
| 159 | -<h3 id="efficient" name="effective">2.2 Efficient</h3> | |
| 159 | +<h3 id="selfcontained" name="selfcontained">2.2 Self Contained</h3> | |
| 160 | 160 | |
| 161 | 161 | Git is actually a collection of many small tools, each doing one small |
| 162 | 162 | part of the job, which can be recombined (by experts) to perform |
| 163 | 163 | powerful operations. Git has a lot of complexity and many dependencies, |
| 164 | 164 | so that most people end up installing it via some kind of package |
| @@ -165,28 +165,30 @@ | ||
| 165 | 165 | manager, simply because the creation of complicated binary packages is |
| 166 | 166 | best delegated to people skilled in their creation. Normal Git users are |
| 167 | 167 | not expected to build Git from source and install it themselves. |
| 168 | 168 | |
| 169 | 169 | Fossil is a single self-contained stand-alone executable which by default |
| 170 | -depends only on common platform libraries. If your platform allows static | |
| 171 | -linking — not all do these days! — you can even get it down to | |
| 172 | -a single executable with no external dependencies at all. Most notably, | |
| 173 | -we deliver the official Windows builds of Fossil this way: the Zip file | |
| 174 | -contains only <tt>fossil.exe</tt>, a self-contained Fossil executable; | |
| 175 | -it is not a <tt>setup.exe</tt> style installer, it is the whole enchilada. | |
| 176 | - | |
| 177 | -A typical Fossil executable is about 5 MiB, not counting system | |
| 178 | -libraries it shares in common with Git such as OpenSSL and zlib, which | |
| 179 | -we can factor out of the discussion. | |
| 180 | - | |
| 181 | -These properties allow Fossil to easily run inside a minimally configured | |
| 182 | -[https://en.wikipedia.org/wiki/Chroot|chroot jail], from a Windows memory | |
| 183 | -stick, off a Raspberry Pi with a tiny SD card, etc. To install Fossil, | |
| 184 | -one merely puts the executable somewhere in the <tt>$PATH</tt>. Fossil is | |
| 185 | -[https://fossil-scm.org/fossil/doc/trunk/www/build.wiki|straightforward | |
| 186 | -to build and install], so that many Fossil users do in fact build and | |
| 187 | -install "trunk" versions to get new features between formal releases. | |
| 170 | +depends only on common platform libraries. You can statically link | |
| 171 | +to get an executable with no external dependencies at all — a useful | |
| 172 | +feature for running inside of restrictive | |
| 173 | +[https://en.wikipedia.org/wiki/Chroot|chroot jail]. | |
| 174 | + | |
| 175 | +The precompiled Fossil binaries are delivered as just a single | |
| 176 | +executable. The precompiled Windows deliveries are just a ZIP archive | |
| 177 | +containing only "<tt>fossil.exe</tt>". There is no "<tt>setup.exe</tt>" | |
| 178 | +to run. Linux and Mac precompiled binaries are a tarball containing | |
| 179 | +just the "<tt>fossil</tt>" executable. To install, just put the | |
| 180 | +executable on your PATH. To uninstall, just delete the executable. | |
| 181 | +To upgrade (or downgrade) simply replace the executable. | |
| 182 | + | |
| 183 | +A typical Fossil executable is between 5 and 7 megabytes uncompressed | |
| 184 | +(as of 2020-12-12), | |
| 185 | +assuming that the executable is statically linked against OpenSSL. | |
| 186 | + | |
| 187 | +Fossil is easy to build from sources. Just run | |
| 188 | +"<tt>./configure && make</tt>" on POSIX systems and | |
| 189 | +"<tt>nmake /f Makefile.msc</tt>" on Windows. | |
| 188 | 190 | |
| 189 | 191 | Contrast a basic installation of Git, which takes up about |
| 190 | 192 | 15 MiB on Debian 10 across 230 files, not counting the contents of |
| 191 | 193 | <tt>/usr/share/doc</tt> or <tt>/usr/share/locale</tt>. If you need to |
| 192 | 194 | deploy to any platform where you cannot count facilities like the POSIX |
| @@ -216,88 +218,92 @@ | ||
| 216 | 218 | resource hungry] and hence more costly to run than the equivalent |
| 217 | 219 | Fossil setup. GitLab's basic requirements are easy to accept when you're dedicating |
| 218 | 220 | a local rack server or blade to it, since its minimum requirements are |
| 219 | 221 | more or less a description of the smallest |
| 220 | 222 | thing you could call a "server" these days, but when you go to host that |
| 221 | -in the cloud, you can expect to pay about 8× as much to comfortably host | |
| 223 | +in the cloud, you can expect to pay about 8 times as much to comfortably host | |
| 222 | 224 | GitLab as for Fossil.³ This difference is largely due to basic |
| 223 | 225 | technology choices: Ruby and PostgreSQL vs C and SQLite. |
| 224 | 226 | |
| 225 | -The Fossil project itself is [./selfhost.wiki|hosted on a very small | |
| 226 | -VPS], and we've received many reports on the Fossil forum about people | |
| 227 | -successfully hosting Fossil service on bare-bones $5/month VPS hosts, | |
| 228 | -spare Raspberry Pi boards, and other small hosts. | |
| 229 | - | |
| 230 | - | |
| 231 | - | |
| 232 | -<h3 id="durable" name="database">2.3 Durable</h3> | |
| 227 | +The Fossil project itself is [./selfhost.wiki|hosted on a small and | |
| 228 | +inexpensive VPS]. A bare-bones $5/month VPS or a | |
| 229 | +spare Raspberry Pi is sufficient to run a full-up project | |
| 230 | +site, complete with tickets, wiki, and forum, in addition to | |
| 231 | +being a code repository. | |
| 232 | + | |
| 233 | +<h3 id="durable" name="database">2.3 Query Language</h3> | |
| 233 | 234 | |
| 234 | 235 | The baseline data structures for Fossil and Git are the same, modulo |
| 235 | 236 | formatting details. Both systems manage a |
| 236 | 237 | [https://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic |
| 237 | 238 | graph] (DAG) of [https://en.wikipedia.org/wiki/Merkle_tree | Merkle |
| 238 | 239 | tree] structured check-in objects. |
| 239 | 240 | Check-ins are identified by a cryptographic hash of the check-in |
| 240 | -contents, and each check-in refers to its parent via <i>its</i> hash. | |
| 241 | +contents, and each check-in refers to its parent via the parent's hash. | |
| 241 | 242 | |
| 242 | 243 | The difference is that Git stores its objects as individual files in the |
| 243 | -<tt>.git</tt> folder or compressed into bespoke | |
| 244 | +<tt>.git</tt> folder or compressed into bespoke key/value | |
| 244 | 245 | [https://git-scm.com/book/en/v2/Git-Internals-Packfiles|pack-files], |
| 245 | 246 | whereas Fossil stores its objects in a [https://www.sqlite.org/|SQLite] |
| 246 | -database file using a hybrid NoSQL/relational data model of the check-in | |
| 247 | -history. Git's data storage system is an ad-hoc pile-of-files key/value | |
| 248 | -database, whereas Fossil uses a proven, | |
| 249 | -[https://sqlite.org/testing.html|heavily-tested], general-purpose, | |
| 250 | -[https://sqlite.org/transactional.html|durable] SQL database. This | |
| 251 | -difference is more than an implementation detail. It has important | |
| 247 | +database file which provides ACID transactions and a high-level query | |
| 248 | +language. | |
| 249 | +This difference is more than an implementation detail. It has important | |
| 252 | 250 | practical consequences. |
| 253 | 251 | |
| 254 | -With Git, one can easily locate the ancestors of a particular check-in | |
| 252 | +One notable consequence is that it is difficult to find the descendents | |
| 253 | +of check-ins in Git. | |
| 254 | +One can easily locate the ancestors of a particular Git check-in | |
| 255 | 255 | by following the pointers embedded in the check-in object, but it is |
| 256 | 256 | difficult to go the other direction and locate the descendants of a |
| 257 | 257 | check-in. It is so difficult, in fact, that neither native Git nor |
| 258 | -GitHub provide this capability short of | |
| 259 | -[http://catb.org/jargon/html/G/grovel.html|groveling] the | |
| 260 | -[https://www.git-scm.com/docs/git-log|commit log]. With Git, if you | |
| 261 | -are looking at some historical check-in then you cannot ask "What came | |
| 262 | -next?" or "What are the children of this check-in?" | |
| 263 | - | |
| 264 | -Fossil, on the other hand, parses essential information about check-ins | |
| 265 | -(parents, children, committers, comments, files changed, etc.) into a | |
| 266 | -relational database that can easily be queried using concise SQL | |
| 267 | -statements to find both ancestors and descendants of a check-in. This is | |
| 268 | -the hybrid data model mentioned above: Fossil manages your check-in and | |
| 269 | -other data in a NoSQL block chain structured data store, but that's backed | |
| 270 | -by a set of relational lookup tables for quick indexing into that | |
| 271 | -artifact store. (See "[./theory1.wiki|Thoughts On The Design Of The | |
| 272 | -Fossil DVCS]" for more details.) | |
| 258 | +GitHub provide this capability short of crawling the | |
| 259 | +[https://www.git-scm.com/docs/git-log|commit log]. With Fossil, | |
| 260 | +on the other hand, finding descendents is a simple SQL query. | |
| 261 | +It is common in Fossil to ask to see | |
| 262 | +[/timeline?d=release&n=all&y=ci&nd|all check-ins since the last release]. | |
| 263 | +Git lets you see "what came before". Fossil makes it just as | |
| 264 | +easy to also see "what came after". | |
| 273 | 265 | |
| 274 | 266 | Leaf check-ins in Git that lack a "ref" become "detached," making them |
| 275 | 267 | difficult to locate and subject to garbage collection. This |
| 276 | 268 | [http://gitfaq.org/articles/what-is-a-detached-head.html|detached head |
| 277 | -state] problem has caused untold grief for | |
| 278 | -[https://www.google.com/search?q=git+detached+head+state | a huge number | |
| 269 | +state] problem has caused grief for | |
| 270 | +[https://www.google.com/search?q=git+detached+head+state | many | |
| 279 | 271 | of Git users]. With |
| 280 | 272 | Fossil, detached heads are simply impossible because we can always find |
| 281 | -our way back into the block chain using one or more of the relational | |
| 282 | -indices it automatically manages for you. | |
| 273 | +our way back into the Merkle tree using one or more of the relations | |
| 274 | +in the SQL database. | |
| 283 | 275 | |
| 284 | -This design difference shows up in several other places within each | |
| 285 | -tool. It is why Fossil's [/help?cmd=timeline|timeline] is generally more | |
| 286 | -detailed yet more clear than those available in Git front-ends. | |
| 287 | -(Contrast [/timeline?c=6df7a853ec16865b|this Fossil timeline] with | |
| 276 | +The SQL query capabilities of Fossil make it easier to track the | |
| 277 | +changes for one particular file within a project. For example, | |
| 278 | +you can easily find | |
| 279 | +[/finfo/www/fossil-v-git.wiki|the complete edit history of this one document], | |
| 280 | +or even | |
| 281 | +[/finfo/www/fossil-v-git.wiki?ubg|the same history color-coded by committer], | |
| 282 | +Both questions are simple SQL query in Fossil, with procedural code | |
| 283 | +only being used to format the result for display. | |
| 284 | +The same result could be obtained from Git, but because the data is | |
| 285 | +in a key/value store, much more procedural code has to be written to | |
| 286 | +walk the data and compute the result. And since that is a lot more | |
| 287 | +work, the question is seldom asked. | |
| 288 | + | |
| 289 | +The ease of querying Fossil data using SQL means that status or | |
| 290 | +history information about the project under management is easier | |
| 291 | +to obtain. And being easier means that it is more likely to happen. | |
| 292 | +Fossil reports tend to be more detailed and useful. | |
| 293 | +Consider the [/timeline?c=6df7a853ec16865b|this Fossil timeline] | |
| 294 | +compared to its | |
| 288 | 295 | [https://github.com/drhsqlite/fossil-mirror/commits/master?after=f720c106d297ca1f61bccb30c5c191b88a626d01+34|its |
| 289 | -closest equivalent in GitHub].) It's why there is no inverse of the | |
| 290 | -cryptic <tt>@~</tt> notation in Git, meaning "the parent of HEAD," which | |
| 291 | -Fossil simply calls "prev", but there <i>is</i> a "next" | |
| 292 | -[./checkin_names.wiki|special check-in name] in Fossil. It is why Fossil | |
| 293 | -has so many [./webpage-ex.md|built-in status reports] to help maintain | |
| 294 | -situational awareness, aid comprehension, and avoid errors. | |
| 295 | - | |
| 296 | -These differences are due, in part, to Fossil's start a year later than | |
| 297 | -Git: we were able to learn from its key design mistakes. | |
| 298 | - | |
| 296 | +closest equivalent in GitHub]. Judge for yourself: Which of those | |
| 297 | +reports is more useful to a developer trying to understand what happened? | |
| 298 | + | |
| 299 | +The bottom line is that even though Fossil and Git are built around | |
| 300 | +the same low-level data structure, the use of SQL | |
| 301 | +to query this data makes the data more accessible in Fossil, resulting | |
| 302 | +in more detailed information being available to the user. This | |
| 303 | +improves situational awareness and makes working on the project | |
| 304 | +easier. | |
| 299 | 305 | |
| 300 | 306 | <h3 id="portable">2.4 Portable</h3> |
| 301 | 307 | |
| 302 | 308 | Fossil is largely written in ISO C, almost purely conforming to the |
| 303 | 309 | original 1989 standard. We make very little use of |
| @@ -530,12 +536,12 @@ | ||
| 530 | 536 | not the best way to hang a picture on the living room wall. |
| 531 | 537 | |
| 532 | 538 | |
| 533 | 539 | <h4 id="contrib">2.5.3 Accepting Contributions</h4> |
| 534 | 540 | |
| 535 | -As of this writing, Git has received about 4.5⨉ as many commits as | |
| 536 | -Fossil resulting in about 2.5⨉ as many lines of source code. The line | |
| 541 | +As of this writing, Git has received about 4.5 times as many commits as | |
| 542 | +Fossil resulting in about 2.5times as many lines of source code. The line | |
| 537 | 543 | count excludes tests and in-tree third-party dependencies. It does not |
| 538 | 544 | exclude the default GUI for each, since it's integral for Fossil, so we |
| 539 | 545 | count the size of <tt>gitk</tt> in this. |
| 540 | 546 | |
| 541 | 547 | It is obvious that Git is bigger in part because of its first-mover |
| @@ -906,11 +912,11 @@ | ||
| 906 | 912 | Almost three years after Fossil solved this problem, the |
| 907 | 913 | [https://sha-mbles.github.io/ | SHAmbles attack] was published, further |
| 908 | 914 | weakening the case for continuing to use SHA-1. |
| 909 | 915 | |
| 910 | 916 | The practical impact of attacks like SHAttered and SHAmbles on the |
| 911 | -Git and Fossil blockchains isn't clear, but you want to have your repositories | |
| 917 | +Git and Fossil Merkle trees isn't clear, but you want to have your repositories | |
| 912 | 918 | moved over to a stronger hash algorithm before someone figures out how |
| 913 | 919 | to make use of the weaknesses in the old one. Fossil has had this covered |
| 914 | 920 | for years now, so that the solution is now almost universally deployed. |
| 915 | 921 | |
| 916 | 922 | <hr/> |
| 917 | 923 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -43,22 +43,22 @@ | |
| 43 | <td>VCS, tickets, wiki, docs, notes, forum, UI, |
| 44 | [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td> |
| 45 | <td><a href="#features">2.1 ↓</a></td> |
| 46 | </tr> |
| 47 | <tr> |
| 48 | <td>Sprawling and inefficient</td> |
| 49 | <td>Self-contained and efficient</td> |
| 50 | <td><a href="#efficient">2.2 ↓</a></td> |
| 51 | </tr> |
| 52 | <tr> |
| 53 | <td>One-off custom pile-of-files data store</td> |
| 54 | <td>[https://sqlite.org/famous.html|The most popular database in the world]</td> |
| 55 | <td><a href="#durable">2.3 ↓</a></td> |
| 56 | </tr> |
| 57 | <tr> |
| 58 | <td>Runs natively on POSIX systems only</td> |
| 59 | <td>Native on common desktop & server platforms</td> |
| 60 | <td><a href="#portable">2.4 ↓</a></td> |
| 61 | </tr> |
| 62 | <tr> |
| 63 | <td>Bazaar-style development</td> |
| 64 | <td>Cathedral-style development</td> |
| @@ -93,12 +93,12 @@ | |
| 93 | <td>Commit first</td> |
| 94 | <td>Test first</td> |
| 95 | <td><a href="#testing">2.8 ↓</a></td> |
| 96 | </tr> |
| 97 | <tr> |
| 98 | <td>SHA-2</td> |
| 99 | <td>SHA-3</td> |
| 100 | <td><a href="#hash">2.9 ↓</a></td> |
| 101 | </tr> |
| 102 | </table></blockquote> |
| 103 | |
| 104 | <h3 id="features">2.1 Featureful</h3> |
| @@ -117,16 +117,16 @@ | |
| 117 | the design. One way to describe Fossil is that it is |
| 118 | "[https://github.com/ | GitHub]-in-a-box." |
| 119 | |
| 120 | Fossil can do operations over all local repo clones and check-out |
| 121 | directories with a single command. For example, Fossil lets you say |
| 122 | <tt>fossil all sync</tt> on a laptop prior to taking it off the network |
| 123 | hosting those repos. You can sync up to all of the private repos on your |
| 124 | company network plus those public Internet-hosted repos you use. Whether |
| 125 | going out for a working lunch or on a transoceanic airplane trip, one |
| 126 | command gets you in sync. This works with several other Fossil |
| 127 | sub-commands, such as <tt>fossil all changes</tt> to get a list of files |
| 128 | that you forgot to commit prior to the end of your working day, across |
| 129 | all repos. |
| 130 | |
| 131 | Whenever Fossil is told to modify the local checkout in some destructive |
| 132 | way ([/help?cmd=rm|fossil rm], [/help?cmd=update|fossil update], |
| @@ -154,11 +154,11 @@ | |
| 154 | history, and so forth.² That means you get a copy of this very article |
| 155 | and all of its historical versions, plus the same for all of the other |
| 156 | public content on this site. |
| 157 | |
| 158 | |
| 159 | <h3 id="efficient" name="effective">2.2 Efficient</h3> |
| 160 | |
| 161 | Git is actually a collection of many small tools, each doing one small |
| 162 | part of the job, which can be recombined (by experts) to perform |
| 163 | powerful operations. Git has a lot of complexity and many dependencies, |
| 164 | so that most people end up installing it via some kind of package |
| @@ -165,28 +165,30 @@ | |
| 165 | manager, simply because the creation of complicated binary packages is |
| 166 | best delegated to people skilled in their creation. Normal Git users are |
| 167 | not expected to build Git from source and install it themselves. |
| 168 | |
| 169 | Fossil is a single self-contained stand-alone executable which by default |
| 170 | depends only on common platform libraries. If your platform allows static |
| 171 | linking — not all do these days! — you can even get it down to |
| 172 | a single executable with no external dependencies at all. Most notably, |
| 173 | we deliver the official Windows builds of Fossil this way: the Zip file |
| 174 | contains only <tt>fossil.exe</tt>, a self-contained Fossil executable; |
| 175 | it is not a <tt>setup.exe</tt> style installer, it is the whole enchilada. |
| 176 | |
| 177 | A typical Fossil executable is about 5 MiB, not counting system |
| 178 | libraries it shares in common with Git such as OpenSSL and zlib, which |
| 179 | we can factor out of the discussion. |
| 180 | |
| 181 | These properties allow Fossil to easily run inside a minimally configured |
| 182 | [https://en.wikipedia.org/wiki/Chroot|chroot jail], from a Windows memory |
| 183 | stick, off a Raspberry Pi with a tiny SD card, etc. To install Fossil, |
| 184 | one merely puts the executable somewhere in the <tt>$PATH</tt>. Fossil is |
| 185 | [https://fossil-scm.org/fossil/doc/trunk/www/build.wiki|straightforward |
| 186 | to build and install], so that many Fossil users do in fact build and |
| 187 | install "trunk" versions to get new features between formal releases. |
| 188 | |
| 189 | Contrast a basic installation of Git, which takes up about |
| 190 | 15 MiB on Debian 10 across 230 files, not counting the contents of |
| 191 | <tt>/usr/share/doc</tt> or <tt>/usr/share/locale</tt>. If you need to |
| 192 | deploy to any platform where you cannot count facilities like the POSIX |
| @@ -216,88 +218,92 @@ | |
| 216 | resource hungry] and hence more costly to run than the equivalent |
| 217 | Fossil setup. GitLab's basic requirements are easy to accept when you're dedicating |
| 218 | a local rack server or blade to it, since its minimum requirements are |
| 219 | more or less a description of the smallest |
| 220 | thing you could call a "server" these days, but when you go to host that |
| 221 | in the cloud, you can expect to pay about 8× as much to comfortably host |
| 222 | GitLab as for Fossil.³ This difference is largely due to basic |
| 223 | technology choices: Ruby and PostgreSQL vs C and SQLite. |
| 224 | |
| 225 | The Fossil project itself is [./selfhost.wiki|hosted on a very small |
| 226 | VPS], and we've received many reports on the Fossil forum about people |
| 227 | successfully hosting Fossil service on bare-bones $5/month VPS hosts, |
| 228 | spare Raspberry Pi boards, and other small hosts. |
| 229 | |
| 230 | |
| 231 | |
| 232 | <h3 id="durable" name="database">2.3 Durable</h3> |
| 233 | |
| 234 | The baseline data structures for Fossil and Git are the same, modulo |
| 235 | formatting details. Both systems manage a |
| 236 | [https://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic |
| 237 | graph] (DAG) of [https://en.wikipedia.org/wiki/Merkle_tree | Merkle |
| 238 | tree] structured check-in objects. |
| 239 | Check-ins are identified by a cryptographic hash of the check-in |
| 240 | contents, and each check-in refers to its parent via <i>its</i> hash. |
| 241 | |
| 242 | The difference is that Git stores its objects as individual files in the |
| 243 | <tt>.git</tt> folder or compressed into bespoke |
| 244 | [https://git-scm.com/book/en/v2/Git-Internals-Packfiles|pack-files], |
| 245 | whereas Fossil stores its objects in a [https://www.sqlite.org/|SQLite] |
| 246 | database file using a hybrid NoSQL/relational data model of the check-in |
| 247 | history. Git's data storage system is an ad-hoc pile-of-files key/value |
| 248 | database, whereas Fossil uses a proven, |
| 249 | [https://sqlite.org/testing.html|heavily-tested], general-purpose, |
| 250 | [https://sqlite.org/transactional.html|durable] SQL database. This |
| 251 | difference is more than an implementation detail. It has important |
| 252 | practical consequences. |
| 253 | |
| 254 | With Git, one can easily locate the ancestors of a particular check-in |
| 255 | by following the pointers embedded in the check-in object, but it is |
| 256 | difficult to go the other direction and locate the descendants of a |
| 257 | check-in. It is so difficult, in fact, that neither native Git nor |
| 258 | GitHub provide this capability short of |
| 259 | [http://catb.org/jargon/html/G/grovel.html|groveling] the |
| 260 | [https://www.git-scm.com/docs/git-log|commit log]. With Git, if you |
| 261 | are looking at some historical check-in then you cannot ask "What came |
| 262 | next?" or "What are the children of this check-in?" |
| 263 | |
| 264 | Fossil, on the other hand, parses essential information about check-ins |
| 265 | (parents, children, committers, comments, files changed, etc.) into a |
| 266 | relational database that can easily be queried using concise SQL |
| 267 | statements to find both ancestors and descendants of a check-in. This is |
| 268 | the hybrid data model mentioned above: Fossil manages your check-in and |
| 269 | other data in a NoSQL block chain structured data store, but that's backed |
| 270 | by a set of relational lookup tables for quick indexing into that |
| 271 | artifact store. (See "[./theory1.wiki|Thoughts On The Design Of The |
| 272 | Fossil DVCS]" for more details.) |
| 273 | |
| 274 | Leaf check-ins in Git that lack a "ref" become "detached," making them |
| 275 | difficult to locate and subject to garbage collection. This |
| 276 | [http://gitfaq.org/articles/what-is-a-detached-head.html|detached head |
| 277 | state] problem has caused untold grief for |
| 278 | [https://www.google.com/search?q=git+detached+head+state | a huge number |
| 279 | of Git users]. With |
| 280 | Fossil, detached heads are simply impossible because we can always find |
| 281 | our way back into the block chain using one or more of the relational |
| 282 | indices it automatically manages for you. |
| 283 | |
| 284 | This design difference shows up in several other places within each |
| 285 | tool. It is why Fossil's [/help?cmd=timeline|timeline] is generally more |
| 286 | detailed yet more clear than those available in Git front-ends. |
| 287 | (Contrast [/timeline?c=6df7a853ec16865b|this Fossil timeline] with |
| 288 | [https://github.com/drhsqlite/fossil-mirror/commits/master?after=f720c106d297ca1f61bccb30c5c191b88a626d01+34|its |
| 289 | closest equivalent in GitHub].) It's why there is no inverse of the |
| 290 | cryptic <tt>@~</tt> notation in Git, meaning "the parent of HEAD," which |
| 291 | Fossil simply calls "prev", but there <i>is</i> a "next" |
| 292 | [./checkin_names.wiki|special check-in name] in Fossil. It is why Fossil |
| 293 | has so many [./webpage-ex.md|built-in status reports] to help maintain |
| 294 | situational awareness, aid comprehension, and avoid errors. |
| 295 | |
| 296 | These differences are due, in part, to Fossil's start a year later than |
| 297 | Git: we were able to learn from its key design mistakes. |
| 298 | |
| 299 | |
| 300 | <h3 id="portable">2.4 Portable</h3> |
| 301 | |
| 302 | Fossil is largely written in ISO C, almost purely conforming to the |
| 303 | original 1989 standard. We make very little use of |
| @@ -530,12 +536,12 @@ | |
| 530 | not the best way to hang a picture on the living room wall. |
| 531 | |
| 532 | |
| 533 | <h4 id="contrib">2.5.3 Accepting Contributions</h4> |
| 534 | |
| 535 | As of this writing, Git has received about 4.5⨉ as many commits as |
| 536 | Fossil resulting in about 2.5⨉ as many lines of source code. The line |
| 537 | count excludes tests and in-tree third-party dependencies. It does not |
| 538 | exclude the default GUI for each, since it's integral for Fossil, so we |
| 539 | count the size of <tt>gitk</tt> in this. |
| 540 | |
| 541 | It is obvious that Git is bigger in part because of its first-mover |
| @@ -906,11 +912,11 @@ | |
| 906 | Almost three years after Fossil solved this problem, the |
| 907 | [https://sha-mbles.github.io/ | SHAmbles attack] was published, further |
| 908 | weakening the case for continuing to use SHA-1. |
| 909 | |
| 910 | The practical impact of attacks like SHAttered and SHAmbles on the |
| 911 | Git and Fossil blockchains isn't clear, but you want to have your repositories |
| 912 | moved over to a stronger hash algorithm before someone figures out how |
| 913 | to make use of the weaknesses in the old one. Fossil has had this covered |
| 914 | for years now, so that the solution is now almost universally deployed. |
| 915 | |
| 916 | <hr/> |
| 917 |
| --- www/fossil-v-git.wiki | |
| +++ www/fossil-v-git.wiki | |
| @@ -43,22 +43,22 @@ | |
| 43 | <td>VCS, tickets, wiki, docs, notes, forum, UI, |
| 44 | [https://en.wikipedia.org/wiki/Role-based_access_control|RBAC]</td> |
| 45 | <td><a href="#features">2.1 ↓</a></td> |
| 46 | </tr> |
| 47 | <tr> |
| 48 | <td>A federation of many small programs</td> |
| 49 | <td>One self-contained, stand-alone executable</td> |
| 50 | <td><a href="#selfcontained">2.2 ↓</a></td> |
| 51 | </tr> |
| 52 | <tr> |
| 53 | <td>Custom key/value data store</td> |
| 54 | <td>[https://sqlite.org/mostdeployed.html|The most used SQL database in the world]</td> |
| 55 | <td><a href="#durable">2.3 ↓</a></td> |
| 56 | </tr> |
| 57 | <tr> |
| 58 | <td>Runs natively on POSIX systems</td> |
| 59 | <td>Runs natively on both POSIX and Windows</td> |
| 60 | <td><a href="#portable">2.4 ↓</a></td> |
| 61 | </tr> |
| 62 | <tr> |
| 63 | <td>Bazaar-style development</td> |
| 64 | <td>Cathedral-style development</td> |
| @@ -93,12 +93,12 @@ | |
| 93 | <td>Commit first</td> |
| 94 | <td>Test first</td> |
| 95 | <td><a href="#testing">2.8 ↓</a></td> |
| 96 | </tr> |
| 97 | <tr> |
| 98 | <td>SHA-1 or SHA-2</td> |
| 99 | <td>SHA-1 and/or SHA-3, in the same repository</td> |
| 100 | <td><a href="#hash">2.9 ↓</a></td> |
| 101 | </tr> |
| 102 | </table></blockquote> |
| 103 | |
| 104 | <h3 id="features">2.1 Featureful</h3> |
| @@ -117,16 +117,16 @@ | |
| 117 | the design. One way to describe Fossil is that it is |
| 118 | "[https://github.com/ | GitHub]-in-a-box." |
| 119 | |
| 120 | Fossil can do operations over all local repo clones and check-out |
| 121 | directories with a single command. For example, Fossil lets you say |
| 122 | "<tt>fossil all sync</tt>" on a laptop prior to taking it off the network |
| 123 | hosting those repos. You can sync up to all of the private repos on your |
| 124 | company network plus those public Internet-hosted repos you use. Whether |
| 125 | going out for a working lunch or on a transoceanic airplane trip, one |
| 126 | command gets you in sync. This works with several other Fossil |
| 127 | sub-commands, such as "<tt>fossil all changes</tt>" to get a list of files |
| 128 | that you forgot to commit prior to the end of your working day, across |
| 129 | all repos. |
| 130 | |
| 131 | Whenever Fossil is told to modify the local checkout in some destructive |
| 132 | way ([/help?cmd=rm|fossil rm], [/help?cmd=update|fossil update], |
| @@ -154,11 +154,11 @@ | |
| 154 | history, and so forth.² That means you get a copy of this very article |
| 155 | and all of its historical versions, plus the same for all of the other |
| 156 | public content on this site. |
| 157 | |
| 158 | |
| 159 | <h3 id="selfcontained" name="selfcontained">2.2 Self Contained</h3> |
| 160 | |
| 161 | Git is actually a collection of many small tools, each doing one small |
| 162 | part of the job, which can be recombined (by experts) to perform |
| 163 | powerful operations. Git has a lot of complexity and many dependencies, |
| 164 | so that most people end up installing it via some kind of package |
| @@ -165,28 +165,30 @@ | |
| 165 | manager, simply because the creation of complicated binary packages is |
| 166 | best delegated to people skilled in their creation. Normal Git users are |
| 167 | not expected to build Git from source and install it themselves. |
| 168 | |
| 169 | Fossil is a single self-contained stand-alone executable which by default |
| 170 | depends only on common platform libraries. You can statically link |
| 171 | to get an executable with no external dependencies at all — a useful |
| 172 | feature for running inside of restrictive |
| 173 | [https://en.wikipedia.org/wiki/Chroot|chroot jail]. |
| 174 | |
| 175 | The precompiled Fossil binaries are delivered as just a single |
| 176 | executable. The precompiled Windows deliveries are just a ZIP archive |
| 177 | containing only "<tt>fossil.exe</tt>". There is no "<tt>setup.exe</tt>" |
| 178 | to run. Linux and Mac precompiled binaries are a tarball containing |
| 179 | just the "<tt>fossil</tt>" executable. To install, just put the |
| 180 | executable on your PATH. To uninstall, just delete the executable. |
| 181 | To upgrade (or downgrade) simply replace the executable. |
| 182 | |
| 183 | A typical Fossil executable is between 5 and 7 megabytes uncompressed |
| 184 | (as of 2020-12-12), |
| 185 | assuming that the executable is statically linked against OpenSSL. |
| 186 | |
| 187 | Fossil is easy to build from sources. Just run |
| 188 | "<tt>./configure && make</tt>" on POSIX systems and |
| 189 | "<tt>nmake /f Makefile.msc</tt>" on Windows. |
| 190 | |
| 191 | Contrast a basic installation of Git, which takes up about |
| 192 | 15 MiB on Debian 10 across 230 files, not counting the contents of |
| 193 | <tt>/usr/share/doc</tt> or <tt>/usr/share/locale</tt>. If you need to |
| 194 | deploy to any platform where you cannot count facilities like the POSIX |
| @@ -216,88 +218,92 @@ | |
| 218 | resource hungry] and hence more costly to run than the equivalent |
| 219 | Fossil setup. GitLab's basic requirements are easy to accept when you're dedicating |
| 220 | a local rack server or blade to it, since its minimum requirements are |
| 221 | more or less a description of the smallest |
| 222 | thing you could call a "server" these days, but when you go to host that |
| 223 | in the cloud, you can expect to pay about 8 times as much to comfortably host |
| 224 | GitLab as for Fossil.³ This difference is largely due to basic |
| 225 | technology choices: Ruby and PostgreSQL vs C and SQLite. |
| 226 | |
| 227 | The Fossil project itself is [./selfhost.wiki|hosted on a small and |
| 228 | inexpensive VPS]. A bare-bones $5/month VPS or a |
| 229 | spare Raspberry Pi is sufficient to run a full-up project |
| 230 | site, complete with tickets, wiki, and forum, in addition to |
| 231 | being a code repository. |
| 232 | |
| 233 | <h3 id="durable" name="database">2.3 Query Language</h3> |
| 234 | |
| 235 | The baseline data structures for Fossil and Git are the same, modulo |
| 236 | formatting details. Both systems manage a |
| 237 | [https://en.wikipedia.org/wiki/Directed_acyclic_graph | directed acyclic |
| 238 | graph] (DAG) of [https://en.wikipedia.org/wiki/Merkle_tree | Merkle |
| 239 | tree] structured check-in objects. |
| 240 | Check-ins are identified by a cryptographic hash of the check-in |
| 241 | contents, and each check-in refers to its parent via the parent's hash. |
| 242 | |
| 243 | The difference is that Git stores its objects as individual files in the |
| 244 | <tt>.git</tt> folder or compressed into bespoke key/value |
| 245 | [https://git-scm.com/book/en/v2/Git-Internals-Packfiles|pack-files], |
| 246 | whereas Fossil stores its objects in a [https://www.sqlite.org/|SQLite] |
| 247 | database file which provides ACID transactions and a high-level query |
| 248 | language. |
| 249 | This difference is more than an implementation detail. It has important |
| 250 | practical consequences. |
| 251 | |
| 252 | One notable consequence is that it is difficult to find the descendents |
| 253 | of check-ins in Git. |
| 254 | One can easily locate the ancestors of a particular Git check-in |
| 255 | by following the pointers embedded in the check-in object, but it is |
| 256 | difficult to go the other direction and locate the descendants of a |
| 257 | check-in. It is so difficult, in fact, that neither native Git nor |
| 258 | GitHub provide this capability short of crawling the |
| 259 | [https://www.git-scm.com/docs/git-log|commit log]. With Fossil, |
| 260 | on the other hand, finding descendents is a simple SQL query. |
| 261 | It is common in Fossil to ask to see |
| 262 | [/timeline?d=release&n=all&y=ci&nd|all check-ins since the last release]. |
| 263 | Git lets you see "what came before". Fossil makes it just as |
| 264 | easy to also see "what came after". |
| 265 | |
| 266 | Leaf check-ins in Git that lack a "ref" become "detached," making them |
| 267 | difficult to locate and subject to garbage collection. This |
| 268 | [http://gitfaq.org/articles/what-is-a-detached-head.html|detached head |
| 269 | state] problem has caused grief for |
| 270 | [https://www.google.com/search?q=git+detached+head+state | many |
| 271 | of Git users]. With |
| 272 | Fossil, detached heads are simply impossible because we can always find |
| 273 | our way back into the Merkle tree using one or more of the relations |
| 274 | in the SQL database. |
| 275 | |
| 276 | The SQL query capabilities of Fossil make it easier to track the |
| 277 | changes for one particular file within a project. For example, |
| 278 | you can easily find |
| 279 | [/finfo/www/fossil-v-git.wiki|the complete edit history of this one document], |
| 280 | or even |
| 281 | [/finfo/www/fossil-v-git.wiki?ubg|the same history color-coded by committer], |
| 282 | Both questions are simple SQL query in Fossil, with procedural code |
| 283 | only being used to format the result for display. |
| 284 | The same result could be obtained from Git, but because the data is |
| 285 | in a key/value store, much more procedural code has to be written to |
| 286 | walk the data and compute the result. And since that is a lot more |
| 287 | work, the question is seldom asked. |
| 288 | |
| 289 | The ease of querying Fossil data using SQL means that status or |
| 290 | history information about the project under management is easier |
| 291 | to obtain. And being easier means that it is more likely to happen. |
| 292 | Fossil reports tend to be more detailed and useful. |
| 293 | Consider the [/timeline?c=6df7a853ec16865b|this Fossil timeline] |
| 294 | compared to its |
| 295 | [https://github.com/drhsqlite/fossil-mirror/commits/master?after=f720c106d297ca1f61bccb30c5c191b88a626d01+34|its |
| 296 | closest equivalent in GitHub]. Judge for yourself: Which of those |
| 297 | reports is more useful to a developer trying to understand what happened? |
| 298 | |
| 299 | The bottom line is that even though Fossil and Git are built around |
| 300 | the same low-level data structure, the use of SQL |
| 301 | to query this data makes the data more accessible in Fossil, resulting |
| 302 | in more detailed information being available to the user. This |
| 303 | improves situational awareness and makes working on the project |
| 304 | easier. |
| 305 | |
| 306 | <h3 id="portable">2.4 Portable</h3> |
| 307 | |
| 308 | Fossil is largely written in ISO C, almost purely conforming to the |
| 309 | original 1989 standard. We make very little use of |
| @@ -530,12 +536,12 @@ | |
| 536 | not the best way to hang a picture on the living room wall. |
| 537 | |
| 538 | |
| 539 | <h4 id="contrib">2.5.3 Accepting Contributions</h4> |
| 540 | |
| 541 | As of this writing, Git has received about 4.5 times as many commits as |
| 542 | Fossil resulting in about 2.5times as many lines of source code. The line |
| 543 | count excludes tests and in-tree third-party dependencies. It does not |
| 544 | exclude the default GUI for each, since it's integral for Fossil, so we |
| 545 | count the size of <tt>gitk</tt> in this. |
| 546 | |
| 547 | It is obvious that Git is bigger in part because of its first-mover |
| @@ -906,11 +912,11 @@ | |
| 912 | Almost three years after Fossil solved this problem, the |
| 913 | [https://sha-mbles.github.io/ | SHAmbles attack] was published, further |
| 914 | weakening the case for continuing to use SHA-1. |
| 915 | |
| 916 | The practical impact of attacks like SHAttered and SHAmbles on the |
| 917 | Git and Fossil Merkle trees isn't clear, but you want to have your repositories |
| 918 | moved over to a stronger hash algorithm before someone figures out how |
| 919 | to make use of the weaknesses in the old one. Fossil has had this covered |
| 920 | for years now, so that the solution is now almost universally deployed. |
| 921 | |
| 922 | <hr/> |
| 923 |
+61
-13
| --- www/gitusers.md | ||
| +++ www/gitusers.md | ||
| @@ -467,14 +467,50 @@ | ||
| 467 | 467 | If you only want to commit _some_ of the changes, list the names |
| 468 | 468 | of the files or directories you want to commit as arguments, like this: |
| 469 | 469 | |
| 470 | 470 | fossil commit src/feature.c doc/feature.md examples/feature |
| 471 | 471 | |
| 472 | -There are currently no interactive patching features in Fossil like | |
| 473 | -`git add --patch/-p` or `git commit -p`. [Contributions welcome!][ctrb] | |
| 472 | +Although there are currently no | |
| 473 | +<a id="csplit"></a>[commit splitting][gcspl] features in Fossil like | |
| 474 | +`git add -p`, `git commit -p`, or `git rebase -i`, you can get the same | |
| 475 | +effect by converting an uncommitted change set to a patch and then | |
| 476 | +running it through [Patchouli]. | |
| 474 | 477 | |
| 475 | -[ctrb]: https://fossil-scm.org/fossil/doc/trunk/www/contribute.wiki | |
| 478 | +Rather than use `fossil diff -i` to produce such a patch, a safer and | |
| 479 | +more idiomatic method would be: | |
| 480 | + | |
| 481 | + fossil stash save -m 'my big ball-o-hackage' | |
| 482 | + fossil stash diff > my-changes.patch | |
| 483 | + | |
| 484 | +That stores your changes in the stash, then lets you operate on a copy | |
| 485 | +of that patch. Each time you re-run the second command, it will take the | |
| 486 | +current state of the working directory into account to produce a | |
| 487 | +potentially different patch, likely smaller because it leaves out patch | |
| 488 | +hunks already applied. | |
| 489 | + | |
| 490 | +In this way, the combination of working tree and stash replaces the need | |
| 491 | +for Git’s index feature. | |
| 492 | + | |
| 493 | +This also solves a philosophical problem with `git commit -p`: how can | |
| 494 | +you test that a split commit doesn’t break anything if you do it as part | |
| 495 | +of the commit action? Git’s lack of an autosync feature means you can | |
| 496 | +commit locally and then rewrite history if the commit doesn’t work out, | |
| 497 | +but we’d rather make changes only to the working directory, test the | |
| 498 | +changes there, and only commit once we’re sure it’s right. | |
| 499 | + | |
| 500 | +This also explains why we don’t have anything like `git rebase -i` | |
| 501 | +to split an existing commit: in Fossil, commits are *commitments,* not | |
| 502 | +something you want to go back and rewrite later. | |
| 503 | + | |
| 504 | +If someone does [contribute][ctrb] a commit splitting feature to Fossil, | |
| 505 | +we’d expect it to be an interactive form of | |
| 506 | +[`fossil stash apply`][stash], rather than follow Git’s ill-considered | |
| 507 | +design leads. | |
| 508 | + | |
| 509 | +[ctrb]: https://fossil-scm.org/fossil/doc/trunk/www/contribute.wiki | |
| 510 | +[gcspl]: https://git-scm.com/docs/git-rebase#_splitting_commits | |
| 511 | +[Patchouli]: https://pypi.org/project/patchouli/ | |
| 476 | 512 | |
| 477 | 513 | |
| 478 | 514 | <a id="bneed"></a> |
| 479 | 515 | ## Create Branches At Point Of Need, Rather Than Ahead of Need |
| 480 | 516 | |
| @@ -632,10 +668,14 @@ | ||
| 632 | 668 | draft was written, it’s been revised multiple times to address less |
| 633 | 669 | common objections as well. Chances are not good that you are going to |
| 634 | 670 | come up with a new objection that we haven’t already considered and |
| 635 | 671 | addressed there. |
| 636 | 672 | |
| 673 | +There is only one sub-feature of `git rebase` that is philosophically | |
| 674 | +compatible with Fossil yet which currently has no functional equivalent. | |
| 675 | +We cover [this and the workaround for it](#csplit) above. | |
| 676 | + | |
| 637 | 677 | [3]: ./rebaseharm.md |
| 638 | 678 | |
| 639 | 679 | |
| 640 | 680 | ## <a id="show"></a> Showing Information About Commits |
| 641 | 681 | |
| @@ -687,20 +727,28 @@ | ||
| 687 | 727 | view][infow], though. |
| 688 | 728 | |
| 689 | 729 | |
| 690 | 730 | #### <a name="dstat"></a> Diff Statistics |
| 691 | 731 | |
| 692 | -Fossil doesn’t have an internal equivalent to commands like | |
| 693 | -`git show --stat`, but it’s easily remedied by using | |
| 694 | -[the widely-available `diffstat` tool][dst]: | |
| 695 | - | |
| 696 | - fossil diff -i --from 2020-04-01 | diffstat | |
| 697 | - | |
| 698 | -We gave the `-i` flag here to force Fossil to use its internal diff | |
| 699 | -implementation, bypassing [your local `diff-command` setting][dcset]. | |
| 700 | -If you had that set to [`colordiff`][cdiff], for example, its output | |
| 701 | -would confuse `diffstat`. | |
| 732 | +Fossil’s closest internal equivalent to commands like | |
| 733 | +`git show --stat` is: | |
| 734 | + | |
| 735 | + fossil diff -i --from 2020-04-01 --numstat | |
| 736 | + | |
| 737 | +The `--numstat` output is a bit cryptic, so we recommend delegating | |
| 738 | +this task to [the widely-available `diffstat` tool][dst]: | |
| 739 | + | |
| 740 | + fossil diff -i -N --from 2020-04-01 | diffstat | |
| 741 | + | |
| 742 | +We gave the `-i` flag in both cases to force Fossil to use its internal | |
| 743 | +diff implementation, bypassing [your local `diff-command` setting][dcset]. | |
| 744 | +The `--numstat` option has no effect when you have an external diff | |
| 745 | +command set, and some diff command alternatives like | |
| 746 | +[`colordiff`][cdiff] produce output that confuses `diffstat`. | |
| 747 | + | |
| 748 | +If you leave off the `-N` flag in the second example, the `diffstat` | |
| 749 | +output won’t include info about any newly-added files. | |
| 702 | 750 | |
| 703 | 751 | [cdiff]: https://www.colordiff.org/ |
| 704 | 752 | [dcset]: https://fossil-scm.org/home/help?cmd=diff-command |
| 705 | 753 | [dst]: https://invisible-island.net/diffstat/diffstat.html |
| 706 | 754 | |
| 707 | 755 |
| --- www/gitusers.md | |
| +++ www/gitusers.md | |
| @@ -467,14 +467,50 @@ | |
| 467 | If you only want to commit _some_ of the changes, list the names |
| 468 | of the files or directories you want to commit as arguments, like this: |
| 469 | |
| 470 | fossil commit src/feature.c doc/feature.md examples/feature |
| 471 | |
| 472 | There are currently no interactive patching features in Fossil like |
| 473 | `git add --patch/-p` or `git commit -p`. [Contributions welcome!][ctrb] |
| 474 | |
| 475 | [ctrb]: https://fossil-scm.org/fossil/doc/trunk/www/contribute.wiki |
| 476 | |
| 477 | |
| 478 | <a id="bneed"></a> |
| 479 | ## Create Branches At Point Of Need, Rather Than Ahead of Need |
| 480 | |
| @@ -632,10 +668,14 @@ | |
| 632 | draft was written, it’s been revised multiple times to address less |
| 633 | common objections as well. Chances are not good that you are going to |
| 634 | come up with a new objection that we haven’t already considered and |
| 635 | addressed there. |
| 636 | |
| 637 | [3]: ./rebaseharm.md |
| 638 | |
| 639 | |
| 640 | ## <a id="show"></a> Showing Information About Commits |
| 641 | |
| @@ -687,20 +727,28 @@ | |
| 687 | view][infow], though. |
| 688 | |
| 689 | |
| 690 | #### <a name="dstat"></a> Diff Statistics |
| 691 | |
| 692 | Fossil doesn’t have an internal equivalent to commands like |
| 693 | `git show --stat`, but it’s easily remedied by using |
| 694 | [the widely-available `diffstat` tool][dst]: |
| 695 | |
| 696 | fossil diff -i --from 2020-04-01 | diffstat |
| 697 | |
| 698 | We gave the `-i` flag here to force Fossil to use its internal diff |
| 699 | implementation, bypassing [your local `diff-command` setting][dcset]. |
| 700 | If you had that set to [`colordiff`][cdiff], for example, its output |
| 701 | would confuse `diffstat`. |
| 702 | |
| 703 | [cdiff]: https://www.colordiff.org/ |
| 704 | [dcset]: https://fossil-scm.org/home/help?cmd=diff-command |
| 705 | [dst]: https://invisible-island.net/diffstat/diffstat.html |
| 706 | |
| 707 |
| --- www/gitusers.md | |
| +++ www/gitusers.md | |
| @@ -467,14 +467,50 @@ | |
| 467 | If you only want to commit _some_ of the changes, list the names |
| 468 | of the files or directories you want to commit as arguments, like this: |
| 469 | |
| 470 | fossil commit src/feature.c doc/feature.md examples/feature |
| 471 | |
| 472 | Although there are currently no |
| 473 | <a id="csplit"></a>[commit splitting][gcspl] features in Fossil like |
| 474 | `git add -p`, `git commit -p`, or `git rebase -i`, you can get the same |
| 475 | effect by converting an uncommitted change set to a patch and then |
| 476 | running it through [Patchouli]. |
| 477 | |
| 478 | Rather than use `fossil diff -i` to produce such a patch, a safer and |
| 479 | more idiomatic method would be: |
| 480 | |
| 481 | fossil stash save -m 'my big ball-o-hackage' |
| 482 | fossil stash diff > my-changes.patch |
| 483 | |
| 484 | That stores your changes in the stash, then lets you operate on a copy |
| 485 | of that patch. Each time you re-run the second command, it will take the |
| 486 | current state of the working directory into account to produce a |
| 487 | potentially different patch, likely smaller because it leaves out patch |
| 488 | hunks already applied. |
| 489 | |
| 490 | In this way, the combination of working tree and stash replaces the need |
| 491 | for Git’s index feature. |
| 492 | |
| 493 | This also solves a philosophical problem with `git commit -p`: how can |
| 494 | you test that a split commit doesn’t break anything if you do it as part |
| 495 | of the commit action? Git’s lack of an autosync feature means you can |
| 496 | commit locally and then rewrite history if the commit doesn’t work out, |
| 497 | but we’d rather make changes only to the working directory, test the |
| 498 | changes there, and only commit once we’re sure it’s right. |
| 499 | |
| 500 | This also explains why we don’t have anything like `git rebase -i` |
| 501 | to split an existing commit: in Fossil, commits are *commitments,* not |
| 502 | something you want to go back and rewrite later. |
| 503 | |
| 504 | If someone does [contribute][ctrb] a commit splitting feature to Fossil, |
| 505 | we’d expect it to be an interactive form of |
| 506 | [`fossil stash apply`][stash], rather than follow Git’s ill-considered |
| 507 | design leads. |
| 508 | |
| 509 | [ctrb]: https://fossil-scm.org/fossil/doc/trunk/www/contribute.wiki |
| 510 | [gcspl]: https://git-scm.com/docs/git-rebase#_splitting_commits |
| 511 | [Patchouli]: https://pypi.org/project/patchouli/ |
| 512 | |
| 513 | |
| 514 | <a id="bneed"></a> |
| 515 | ## Create Branches At Point Of Need, Rather Than Ahead of Need |
| 516 | |
| @@ -632,10 +668,14 @@ | |
| 668 | draft was written, it’s been revised multiple times to address less |
| 669 | common objections as well. Chances are not good that you are going to |
| 670 | come up with a new objection that we haven’t already considered and |
| 671 | addressed there. |
| 672 | |
| 673 | There is only one sub-feature of `git rebase` that is philosophically |
| 674 | compatible with Fossil yet which currently has no functional equivalent. |
| 675 | We cover [this and the workaround for it](#csplit) above. |
| 676 | |
| 677 | [3]: ./rebaseharm.md |
| 678 | |
| 679 | |
| 680 | ## <a id="show"></a> Showing Information About Commits |
| 681 | |
| @@ -687,20 +727,28 @@ | |
| 727 | view][infow], though. |
| 728 | |
| 729 | |
| 730 | #### <a name="dstat"></a> Diff Statistics |
| 731 | |
| 732 | Fossil’s closest internal equivalent to commands like |
| 733 | `git show --stat` is: |
| 734 | |
| 735 | fossil diff -i --from 2020-04-01 --numstat |
| 736 | |
| 737 | The `--numstat` output is a bit cryptic, so we recommend delegating |
| 738 | this task to [the widely-available `diffstat` tool][dst]: |
| 739 | |
| 740 | fossil diff -i -N --from 2020-04-01 | diffstat |
| 741 | |
| 742 | We gave the `-i` flag in both cases to force Fossil to use its internal |
| 743 | diff implementation, bypassing [your local `diff-command` setting][dcset]. |
| 744 | The `--numstat` option has no effect when you have an external diff |
| 745 | command set, and some diff command alternatives like |
| 746 | [`colordiff`][cdiff] produce output that confuses `diffstat`. |
| 747 | |
| 748 | If you leave off the `-N` flag in the second example, the `diffstat` |
| 749 | output won’t include info about any newly-added files. |
| 750 | |
| 751 | [cdiff]: https://www.colordiff.org/ |
| 752 | [dcset]: https://fossil-scm.org/home/help?cmd=diff-command |
| 753 | [dst]: https://invisible-island.net/diffstat/diffstat.html |
| 754 | |
| 755 |
+28
-45
| --- www/rebaseharm.md | ||
| +++ www/rebaseharm.md | ||
| @@ -298,63 +298,46 @@ | ||
| 298 | 298 | ## <a name="lying"></a>5.0 Rebasing is lying about the project history |
| 299 | 299 | |
| 300 | 300 | By discarding parentage information, rebase attempts to deceive the |
| 301 | 301 | reader about how the code actually came together. |
| 302 | 302 | |
| 303 | -The [Git rebase documentation][gitrebase] admits as much. They acknowledge | |
| 304 | -that when you view a repository as record of what actually happened, | |
| 305 | -doing a rebase is "blasphemous" and "you're _lying_ about what | |
| 306 | -actually happened", but then goes on to justify rebase as follows: | |
| 307 | - | |
| 308 | -> | |
| 309 | -_"The opposing point of view is that the commit history is the **story of | |
| 310 | -how your project was made.** You wouldn't publish the first draft of a | |
| 311 | -book, and the manual for how to maintain your software deserves careful | |
| 312 | -editing. This is the camp that uses tools like rebase and filter-branch | |
| 313 | -to tell the story in the way that's best for future readers."_ | |
| 314 | - | |
| 315 | -This counter-argument assumes you must | |
| 316 | -change history in order to enhance readability, which is not true. | |
| 317 | - | |
| 318 | -In fairness to the Git documentation authors, changing the | |
| 319 | -project history appears to be the only way to make editorial | |
| 320 | -changes in Git. | |
| 321 | -But it does not have to be that way. | |
| 322 | -Fossil demonstrates how "the story of your project" | |
| 323 | -can be enhanced without changing the actual history | |
| 324 | -by allowing users to: | |
| 303 | +You may be tempted to dismiss this as an anti-Git opinion on a Fossil | |
| 304 | +web site, but it’s spelled out just like that [in the Git rebase | |
| 305 | +documentation][gitrebase]. It speaks of “lying,” “telling stories,” | |
| 306 | +and “blasphemy.” | |
| 307 | + | |
| 308 | +That section of the Git docs is contrasting rebase with merge, which we | |
| 309 | +cover [above](#cap-loss), but Git’s rebase feature is more than just an | |
| 310 | +alternative to merging: it also provides mechanisms for changing the | |
| 311 | +project history in order to make editorial changes. Fossil shows that | |
| 312 | +you can get similar effects without modifying historical records, | |
| 313 | +allowing users to: | |
| 325 | 314 | |
| 326 | 315 | 1. Edit check-in comments to fix typos or enhance clarity |
| 327 | 316 | 2. Attach supplemental notes to check-ins or whole branches |
| 328 | - 3. Cross-reference check-ins with each other, or with | |
| 329 | - wiki, tickets, forum posts, and/or embedded documentation | |
| 330 | - 4. Hide ill-conceived or now-unused branches from routine display | |
| 331 | - 5. Fix faulty check-in date/times resulting from misconfigured | |
| 317 | + 3. Hide ill-conceived or now-unused branches from routine display | |
| 318 | + 4. Fix faulty check-in date/times resulting from misconfigured | |
| 332 | 319 | system clocks |
| 320 | + 5. Cross-reference check-ins with each other, or with | |
| 321 | + wiki, tickets, forum posts, and/or embedded documentation | |
| 333 | 322 | |
| 334 | 323 | …and so forth. |
| 335 | 324 | |
| 336 | -These changes are accomplished not by removing or modifying existing | |
| 325 | +Fossil allows all of this not by removing or modifying existing | |
| 337 | 326 | repository entries, but rather by adding new supplemental records. |
| 338 | -The original incorrect or unclear inputs are preserved and are | |
| 339 | -readily accessible. The original history is preserved. | |
| 340 | -But for routine display purposes, the more | |
| 341 | -readable edited presentation is provided. | |
| 342 | - | |
| 343 | -A repository can be a true and accurate | |
| 344 | -representation of history even without getting everything perfect | |
| 345 | -on the first draft. Those are not contradictory goals, at least | |
| 346 | -not in theory. | |
| 347 | - | |
| 348 | -Unfortunately, Git does not currently provide the ability to add | |
| 349 | -corrections or clarifications or supplimental notes to historical check-ins. | |
| 350 | -Hence, once again, | |
| 351 | -rebase can be seen as an attempt to work around limitations | |
| 352 | -of Git. Git could be enhanced to support editorial changes | |
| 353 | -to check-ins. | |
| 354 | -Wouldn't it be better to fix the version control tool | |
| 355 | -rather than requiring users to fabricate a fictitious project history? | |
| 327 | +Fossil keeps the original incorrect or unclear inputs and makes them | |
| 328 | +readily accessible, preserving the original historical record. Fossil | |
| 329 | +doesn’t make the user tell counter-factual “stories,” it only allows the | |
| 330 | +user to provide annotations to provide a more readable edited | |
| 331 | +presentation for routine display purposes. | |
| 332 | + | |
| 333 | +Git needs rebase because it lacks these annotation facilities. Rather | |
| 334 | +than consider rebase a desirable feature missing in Fossil, ask instead | |
| 335 | +why Git lacks support for making editorial changes to check-ins without | |
| 336 | +modifyihng history? Wouldn't it be better to fix the version control | |
| 337 | +tool rather than requiring users to fabricate a fictitious project | |
| 338 | +history? | |
| 356 | 339 | |
| 357 | 340 | ## <a name="collapsing"></a>6.0 Collapsing check-ins throws away valuable information |
| 358 | 341 | |
| 359 | 342 | One of the oft-cited advantages of rebasing in Git is that it lets you |
| 360 | 343 | collapse multiple check-ins down to a single check-in to make the |
| 361 | 344 |
| --- www/rebaseharm.md | |
| +++ www/rebaseharm.md | |
| @@ -298,63 +298,46 @@ | |
| 298 | ## <a name="lying"></a>5.0 Rebasing is lying about the project history |
| 299 | |
| 300 | By discarding parentage information, rebase attempts to deceive the |
| 301 | reader about how the code actually came together. |
| 302 | |
| 303 | The [Git rebase documentation][gitrebase] admits as much. They acknowledge |
| 304 | that when you view a repository as record of what actually happened, |
| 305 | doing a rebase is "blasphemous" and "you're _lying_ about what |
| 306 | actually happened", but then goes on to justify rebase as follows: |
| 307 | |
| 308 | > |
| 309 | _"The opposing point of view is that the commit history is the **story of |
| 310 | how your project was made.** You wouldn't publish the first draft of a |
| 311 | book, and the manual for how to maintain your software deserves careful |
| 312 | editing. This is the camp that uses tools like rebase and filter-branch |
| 313 | to tell the story in the way that's best for future readers."_ |
| 314 | |
| 315 | This counter-argument assumes you must |
| 316 | change history in order to enhance readability, which is not true. |
| 317 | |
| 318 | In fairness to the Git documentation authors, changing the |
| 319 | project history appears to be the only way to make editorial |
| 320 | changes in Git. |
| 321 | But it does not have to be that way. |
| 322 | Fossil demonstrates how "the story of your project" |
| 323 | can be enhanced without changing the actual history |
| 324 | by allowing users to: |
| 325 | |
| 326 | 1. Edit check-in comments to fix typos or enhance clarity |
| 327 | 2. Attach supplemental notes to check-ins or whole branches |
| 328 | 3. Cross-reference check-ins with each other, or with |
| 329 | wiki, tickets, forum posts, and/or embedded documentation |
| 330 | 4. Hide ill-conceived or now-unused branches from routine display |
| 331 | 5. Fix faulty check-in date/times resulting from misconfigured |
| 332 | system clocks |
| 333 | |
| 334 | …and so forth. |
| 335 | |
| 336 | These changes are accomplished not by removing or modifying existing |
| 337 | repository entries, but rather by adding new supplemental records. |
| 338 | The original incorrect or unclear inputs are preserved and are |
| 339 | readily accessible. The original history is preserved. |
| 340 | But for routine display purposes, the more |
| 341 | readable edited presentation is provided. |
| 342 | |
| 343 | A repository can be a true and accurate |
| 344 | representation of history even without getting everything perfect |
| 345 | on the first draft. Those are not contradictory goals, at least |
| 346 | not in theory. |
| 347 | |
| 348 | Unfortunately, Git does not currently provide the ability to add |
| 349 | corrections or clarifications or supplimental notes to historical check-ins. |
| 350 | Hence, once again, |
| 351 | rebase can be seen as an attempt to work around limitations |
| 352 | of Git. Git could be enhanced to support editorial changes |
| 353 | to check-ins. |
| 354 | Wouldn't it be better to fix the version control tool |
| 355 | rather than requiring users to fabricate a fictitious project history? |
| 356 | |
| 357 | ## <a name="collapsing"></a>6.0 Collapsing check-ins throws away valuable information |
| 358 | |
| 359 | One of the oft-cited advantages of rebasing in Git is that it lets you |
| 360 | collapse multiple check-ins down to a single check-in to make the |
| 361 |
| --- www/rebaseharm.md | |
| +++ www/rebaseharm.md | |
| @@ -298,63 +298,46 @@ | |
| 298 | ## <a name="lying"></a>5.0 Rebasing is lying about the project history |
| 299 | |
| 300 | By discarding parentage information, rebase attempts to deceive the |
| 301 | reader about how the code actually came together. |
| 302 | |
| 303 | You may be tempted to dismiss this as an anti-Git opinion on a Fossil |
| 304 | web site, but it’s spelled out just like that [in the Git rebase |
| 305 | documentation][gitrebase]. It speaks of “lying,” “telling stories,” |
| 306 | and “blasphemy.” |
| 307 | |
| 308 | That section of the Git docs is contrasting rebase with merge, which we |
| 309 | cover [above](#cap-loss), but Git’s rebase feature is more than just an |
| 310 | alternative to merging: it also provides mechanisms for changing the |
| 311 | project history in order to make editorial changes. Fossil shows that |
| 312 | you can get similar effects without modifying historical records, |
| 313 | allowing users to: |
| 314 | |
| 315 | 1. Edit check-in comments to fix typos or enhance clarity |
| 316 | 2. Attach supplemental notes to check-ins or whole branches |
| 317 | 3. Hide ill-conceived or now-unused branches from routine display |
| 318 | 4. Fix faulty check-in date/times resulting from misconfigured |
| 319 | system clocks |
| 320 | 5. Cross-reference check-ins with each other, or with |
| 321 | wiki, tickets, forum posts, and/or embedded documentation |
| 322 | |
| 323 | …and so forth. |
| 324 | |
| 325 | Fossil allows all of this not by removing or modifying existing |
| 326 | repository entries, but rather by adding new supplemental records. |
| 327 | Fossil keeps the original incorrect or unclear inputs and makes them |
| 328 | readily accessible, preserving the original historical record. Fossil |
| 329 | doesn’t make the user tell counter-factual “stories,” it only allows the |
| 330 | user to provide annotations to provide a more readable edited |
| 331 | presentation for routine display purposes. |
| 332 | |
| 333 | Git needs rebase because it lacks these annotation facilities. Rather |
| 334 | than consider rebase a desirable feature missing in Fossil, ask instead |
| 335 | why Git lacks support for making editorial changes to check-ins without |
| 336 | modifyihng history? Wouldn't it be better to fix the version control |
| 337 | tool rather than requiring users to fabricate a fictitious project |
| 338 | history? |
| 339 | |
| 340 | ## <a name="collapsing"></a>6.0 Collapsing check-ins throws away valuable information |
| 341 | |
| 342 | One of the oft-cited advantages of rebasing in Git is that it lets you |
| 343 | collapse multiple check-ins down to a single check-in to make the |
| 344 |
+15
| --- www/serverext.wiki | ||
| +++ www/serverext.wiki | ||
| @@ -129,10 +129,11 @@ | ||
| 129 | 129 | * AUTH_CONTENT |
| 130 | 130 | * CONTENT_LENGTH |
| 131 | 131 | * CONTENT_TYPE |
| 132 | 132 | * DOCUMENT_ROOT |
| 133 | 133 | * GATEWAY_INTERFACE |
| 134 | + * HTTPS | |
| 134 | 135 | * HTTP_ACCEPT |
| 135 | 136 | * HTTP_ACCEPT_ENCODING |
| 136 | 137 | * HTTP_COOKIE |
| 137 | 138 | * HTTP_HOST |
| 138 | 139 | * HTTP_IF_MODIFIED_SINCE |
| @@ -142,10 +143,11 @@ | ||
| 142 | 143 | * PATH_INFO |
| 143 | 144 | * QUERY_STRING |
| 144 | 145 | * REMOTE_ADDR |
| 145 | 146 | * REMOTE_USER |
| 146 | 147 | * REQUEST_METHOD |
| 148 | + * REQUEST_SCHEME | |
| 147 | 149 | * REQUEST_URI |
| 148 | 150 | * SCRIPT_DIRECTORY |
| 149 | 151 | * SCRIPT_FILENAME |
| 150 | 152 | * SCRIPT_NAME |
| 151 | 153 | * SERVER_NAME |
| @@ -209,10 +211,11 @@ | ||
| 209 | 211 | <h3>3.1 Input Content</h3> |
| 210 | 212 | |
| 211 | 213 | If the HTTP request includes content (for example if this is a POST request) |
| 212 | 214 | then the CONTENT_LENGTH value will be positive and the data for the content |
| 213 | 215 | will be readable on standard input. |
| 216 | + | |
| 214 | 217 | |
| 215 | 218 | <h2>4.0 CGI Outputs</h2> |
| 216 | 219 | |
| 217 | 220 | CGI programs construct a reply by writing to standard output. The first |
| 218 | 221 | few lines of output are parameters intended for the web server that invoked |
| @@ -254,10 +257,22 @@ | ||
| 254 | 257 | "data-title" attribute. |
| 255 | 258 | |
| 256 | 259 | Except for the three cases noted above, Fossil makes no changes or |
| 257 | 260 | additions to the CGI-generated content. Fossil just passes the verbatim |
| 258 | 261 | content back up the stack towards the requester. |
| 262 | + | |
| 263 | +<h3>4.1 <tt>GATEWAY_INTERFACE</tt> and Recursive Calls to fossil</h3> | |
| 264 | + | |
| 265 | +Like many CGI-aware applications, if fossil sees the environment | |
| 266 | +variable <tt>GATEWAY_INTERFACE</tt> when it starts up, it assumes it | |
| 267 | +is running in a CGI environment and behaves differently than when it | |
| 268 | +is run in a non-CGI interactive session. If you intend to run fossil | |
| 269 | +itself from within an extension CGI script, e.g. to run a query | |
| 270 | +against the repository or simply fetch the fossil binary version, make | |
| 271 | +sure to <em>unset</em> the <tt>GATEWAY_INTERFACE</tt> environment | |
| 272 | +variable before doing so, otherwise the invocation will behave as if | |
| 273 | +it's being run in CGI mode. | |
| 259 | 274 | |
| 260 | 275 | <h2>5.0 Filename Restrictions</h2> |
| 261 | 276 | |
| 262 | 277 | For security reasons, Fossil places restrictions on the names of files |
| 263 | 278 | in the extroot directory that can participate in the extension CGI |
| 264 | 279 |
| --- www/serverext.wiki | |
| +++ www/serverext.wiki | |
| @@ -129,10 +129,11 @@ | |
| 129 | * AUTH_CONTENT |
| 130 | * CONTENT_LENGTH |
| 131 | * CONTENT_TYPE |
| 132 | * DOCUMENT_ROOT |
| 133 | * GATEWAY_INTERFACE |
| 134 | * HTTP_ACCEPT |
| 135 | * HTTP_ACCEPT_ENCODING |
| 136 | * HTTP_COOKIE |
| 137 | * HTTP_HOST |
| 138 | * HTTP_IF_MODIFIED_SINCE |
| @@ -142,10 +143,11 @@ | |
| 142 | * PATH_INFO |
| 143 | * QUERY_STRING |
| 144 | * REMOTE_ADDR |
| 145 | * REMOTE_USER |
| 146 | * REQUEST_METHOD |
| 147 | * REQUEST_URI |
| 148 | * SCRIPT_DIRECTORY |
| 149 | * SCRIPT_FILENAME |
| 150 | * SCRIPT_NAME |
| 151 | * SERVER_NAME |
| @@ -209,10 +211,11 @@ | |
| 209 | <h3>3.1 Input Content</h3> |
| 210 | |
| 211 | If the HTTP request includes content (for example if this is a POST request) |
| 212 | then the CONTENT_LENGTH value will be positive and the data for the content |
| 213 | will be readable on standard input. |
| 214 | |
| 215 | <h2>4.0 CGI Outputs</h2> |
| 216 | |
| 217 | CGI programs construct a reply by writing to standard output. The first |
| 218 | few lines of output are parameters intended for the web server that invoked |
| @@ -254,10 +257,22 @@ | |
| 254 | "data-title" attribute. |
| 255 | |
| 256 | Except for the three cases noted above, Fossil makes no changes or |
| 257 | additions to the CGI-generated content. Fossil just passes the verbatim |
| 258 | content back up the stack towards the requester. |
| 259 | |
| 260 | <h2>5.0 Filename Restrictions</h2> |
| 261 | |
| 262 | For security reasons, Fossil places restrictions on the names of files |
| 263 | in the extroot directory that can participate in the extension CGI |
| 264 |
| --- www/serverext.wiki | |
| +++ www/serverext.wiki | |
| @@ -129,10 +129,11 @@ | |
| 129 | * AUTH_CONTENT |
| 130 | * CONTENT_LENGTH |
| 131 | * CONTENT_TYPE |
| 132 | * DOCUMENT_ROOT |
| 133 | * GATEWAY_INTERFACE |
| 134 | * HTTPS |
| 135 | * HTTP_ACCEPT |
| 136 | * HTTP_ACCEPT_ENCODING |
| 137 | * HTTP_COOKIE |
| 138 | * HTTP_HOST |
| 139 | * HTTP_IF_MODIFIED_SINCE |
| @@ -142,10 +143,11 @@ | |
| 143 | * PATH_INFO |
| 144 | * QUERY_STRING |
| 145 | * REMOTE_ADDR |
| 146 | * REMOTE_USER |
| 147 | * REQUEST_METHOD |
| 148 | * REQUEST_SCHEME |
| 149 | * REQUEST_URI |
| 150 | * SCRIPT_DIRECTORY |
| 151 | * SCRIPT_FILENAME |
| 152 | * SCRIPT_NAME |
| 153 | * SERVER_NAME |
| @@ -209,10 +211,11 @@ | |
| 211 | <h3>3.1 Input Content</h3> |
| 212 | |
| 213 | If the HTTP request includes content (for example if this is a POST request) |
| 214 | then the CONTENT_LENGTH value will be positive and the data for the content |
| 215 | will be readable on standard input. |
| 216 | |
| 217 | |
| 218 | <h2>4.0 CGI Outputs</h2> |
| 219 | |
| 220 | CGI programs construct a reply by writing to standard output. The first |
| 221 | few lines of output are parameters intended for the web server that invoked |
| @@ -254,10 +257,22 @@ | |
| 257 | "data-title" attribute. |
| 258 | |
| 259 | Except for the three cases noted above, Fossil makes no changes or |
| 260 | additions to the CGI-generated content. Fossil just passes the verbatim |
| 261 | content back up the stack towards the requester. |
| 262 | |
| 263 | <h3>4.1 <tt>GATEWAY_INTERFACE</tt> and Recursive Calls to fossil</h3> |
| 264 | |
| 265 | Like many CGI-aware applications, if fossil sees the environment |
| 266 | variable <tt>GATEWAY_INTERFACE</tt> when it starts up, it assumes it |
| 267 | is running in a CGI environment and behaves differently than when it |
| 268 | is run in a non-CGI interactive session. If you intend to run fossil |
| 269 | itself from within an extension CGI script, e.g. to run a query |
| 270 | against the repository or simply fetch the fossil binary version, make |
| 271 | sure to <em>unset</em> the <tt>GATEWAY_INTERFACE</tt> environment |
| 272 | variable before doing so, otherwise the invocation will behave as if |
| 273 | it's being run in CGI mode. |
| 274 | |
| 275 | <h2>5.0 Filename Restrictions</h2> |
| 276 | |
| 277 | For security reasons, Fossil places restrictions on the names of files |
| 278 | in the extroot directory that can participate in the extension CGI |
| 279 |