Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch ben-testing Excluding Merge-Ins
This is equivalent to a diff from 073725ae0c to 47b5bf7d16
2011-08-14
| ||
23:14 | Merge the ben-testing branch into trunk. check-in: 9a0c995826 user: drh tags: trunk | |
23:12 | Fix the file_relative_name() function so that it works on windows. Closed-Leaf check-in: 47b5bf7d16 user: drh tags: ben-testing | |
17:54 | Remove the seperate versionable version of db_get(), which now uses ctrlSettings to determine whether a setting is versionable or not. check-in: 3113f7b18f user: ben tags: ben-testing | |
07:21 | Merge trunk into ben-testing, adjusting for versionable settings. check-in: 246ac307bb user: ben tags: ben-testing | |
2011-08-12
| ||
12:13 | Fix harmless compiler warnings in tar.c. check-in: 073725ae0c user: drh tags: trunk | |
11:54 | When forcing a rollback following an error, reset all SQL statement first so that the rollback can be successful. check-in: 9515143de5 user: drh tags: trunk | |
Changes to src/checkin.c.
30 30 ** 31 31 ** If missingIsFatal is true, then any files that are missing or which 32 32 ** are not true files results in a fatal error. 33 33 */ 34 34 static void status_report( 35 35 Blob *report, /* Append the status report here */ 36 36 const char *zPrefix, /* Prefix on each line of the report */ 37 - int missingIsFatal /* MISSING and NOT_A_FILE are fatal errors */ 37 + int missingIsFatal, /* MISSING and NOT_A_FILE are fatal errors */ 38 + int cwdRelative /* Report relative to the current working dir */ 38 39 ){ 39 40 Stmt q; 40 41 int nPrefix = strlen(zPrefix); 41 42 int nErr = 0; 43 + Blob rewrittenPathname; 42 44 db_prepare(&q, 43 45 "SELECT pathname, deleted, chnged, rid, coalesce(origname!=pathname,0)" 44 46 " FROM vfile " 45 47 " WHERE file_is_selected(id)" 46 48 " AND (chnged OR deleted OR rid=0 OR pathname!=origname) ORDER BY 1" 47 49 ); 50 + blob_zero(&rewrittenPathname); 48 51 while( db_step(&q)==SQLITE_ROW ){ 49 52 const char *zPathname = db_column_text(&q,0); 53 + const char *zDisplayName = zPathname; 50 54 int isDeleted = db_column_int(&q, 1); 51 55 int isChnged = db_column_int(&q,2); 52 56 int isNew = db_column_int(&q,3)==0; 53 57 int isRenamed = db_column_int(&q,4); 54 58 char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); 59 + if( cwdRelative ){ 60 + file_relative_name(zFullName, &rewrittenPathname); 61 + zDisplayName = blob_str(&rewrittenPathname); 62 + if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){ 63 + zDisplayName += 2; /* no unnecessary ./ prefix */ 64 + } 65 + } 55 66 blob_append(report, zPrefix, nPrefix); 56 67 if( isDeleted ){ 57 - blob_appendf(report, "DELETED %s\n", zPathname); 68 + blob_appendf(report, "DELETED %s\n", zDisplayName); 58 69 }else if( !file_isfile(zFullName) ){ 59 70 if( file_access(zFullName, 0)==0 ){ 60 - blob_appendf(report, "NOT_A_FILE %s\n", zPathname); 71 + blob_appendf(report, "NOT_A_FILE %s\n", zDisplayName); 61 72 if( missingIsFatal ){ 62 - fossil_warning("not a file: %s", zPathname); 73 + fossil_warning("not a file: %s", zDisplayName); 63 74 nErr++; 64 75 } 65 76 }else{ 66 - blob_appendf(report, "MISSING %s\n", zPathname); 77 + blob_appendf(report, "MISSING %s\n", zDisplayName); 67 78 if( missingIsFatal ){ 68 - fossil_warning("missing file: %s", zPathname); 79 + fossil_warning("missing file: %s", zDisplayName); 69 80 nErr++; 70 81 } 71 82 } 72 83 }else if( isNew ){ 73 - blob_appendf(report, "ADDED %s\n", zPathname); 84 + blob_appendf(report, "ADDED %s\n", zDisplayName); 74 85 }else if( isDeleted ){ 75 - blob_appendf(report, "DELETED %s\n", zPathname); 86 + blob_appendf(report, "DELETED %s\n", zDisplayName); 76 87 }else if( isChnged==2 ){ 77 - blob_appendf(report, "UPDATED_BY_MERGE %s\n", zPathname); 88 + blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName); 78 89 }else if( isChnged==3 ){ 79 - blob_appendf(report, "ADDED_BY_MERGE %s\n", zPathname); 90 + blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); 80 91 }else if( isChnged==1 ){ 81 - blob_appendf(report, "EDITED %s\n", zPathname); 92 + blob_appendf(report, "EDITED %s\n", zDisplayName); 82 93 }else if( isRenamed ){ 83 - blob_appendf(report, "RENAMED %s\n", zPathname); 94 + blob_appendf(report, "RENAMED %s\n", zDisplayName); 84 95 } 85 96 free(zFullName); 86 97 } 98 + blob_reset(&rewrittenPathname); 87 99 db_finalize(&q); 88 100 db_prepare(&q, "SELECT uuid FROM vmerge JOIN blob ON merge=rid" 89 101 " WHERE id=0"); 90 102 while( db_step(&q)==SQLITE_ROW ){ 91 103 blob_append(report, zPrefix, nPrefix); 92 104 blob_appendf(report, "MERGED_WITH %s\n", db_column_text(&q, 0)); 93 105 } 94 106 db_finalize(&q); 95 107 if( nErr ){ 96 108 fossil_fatal("aborting due to prior errors"); 97 109 } 98 110 } 111 + 112 +/* 113 +** Use the "relative-paths" setting and the --abs-paths and 114 +** --rel-paths command line options to determine whether the 115 +** status report should be shown relative to the current 116 +** working directory. 117 +*/ 118 +static int determine_cwd_relative_option() 119 +{ 120 + int relativePaths = db_get_boolean("relative-paths", 1); 121 + int absPathOption = find_option("abs-paths", 0, 0)!=0; 122 + int relPathOption = find_option("rel-paths", 0, 0)!=0; 123 + if( absPathOption ){ relativePaths = 0; } 124 + if( relPathOption ){ relativePaths = 1; } 125 + return relativePaths; 126 +} 99 127 100 128 /* 101 129 ** COMMAND: changes 102 130 ** 103 131 ** Usage: %fossil changes 104 132 ** 105 133 ** Report on the edit status of all files in the current checkout. 106 134 ** See also the "status" and "extra" commands. 107 135 ** 136 +** Pathnames are displayed according to the "relative-paths" setting, 137 +** unless overridden by the --abs-paths or --rel-paths options. 138 +** 108 139 ** Options: 109 140 ** 110 141 ** --sha1sum Verify file status using SHA1 hashing rather 111 142 ** than relying on file mtimes. 143 +** 144 +** --abs-paths Display absolute pathnames. 145 +** 146 +** --rel-paths Display pathnames relative to the current working 147 +** directory. 112 148 */ 113 149 void changes_cmd(void){ 114 150 Blob report; 115 151 int vid; 116 152 int useSha1sum = find_option("sha1sum", 0, 0)!=0; 153 + int cwdRelative = 0; 117 154 db_must_be_within_tree(); 155 + cwdRelative = determine_cwd_relative_option(); 118 156 blob_zero(&report); 119 157 vid = db_lget_int("checkout", 0); 120 158 vfile_check_signature(vid, 0, useSha1sum); 121 - status_report(&report, "", 0); 159 + status_report(&report, "", 0, cwdRelative); 122 160 blob_write_to_file(&report, "-"); 123 161 } 124 162 125 163 /* 126 164 ** COMMAND: status 127 165 ** 128 166 ** Usage: %fossil status 129 167 ** 130 168 ** Report on the status of the current checkout. 131 169 ** 170 +** Pathnames are displayed according to the "relative-paths" setting, 171 +** unless overridden by the --abs-paths or --rel-paths options. 172 +** 132 173 ** Options: 133 174 ** 134 175 ** --sha1sum Verify file status using SHA1 hashing rather 135 176 ** than relying on file mtimes. 177 +** 178 +** --abs-paths Display absolute pathnames. 179 +** 180 +** --rel-paths Display pathnames relative to the current working 181 +** directory. 136 182 */ 137 183 void status_cmd(void){ 138 184 int vid; 139 185 db_must_be_within_tree(); 140 186 /* 012345678901234 */ 141 187 fossil_print("repository: %s\n", db_lget("repository","")); 142 188 fossil_print("local-root: %s\n", g.zLocalRoot); ................................................................................ 210 256 ** 211 257 ** Files and subdirectories whose names begin with "." are normally 212 258 ** ignored but can be included by adding the --dotfiles option. 213 259 ** 214 260 ** The GLOBPATTERN is a comma-separated list of GLOB expressions for 215 261 ** files that are ignored. The GLOBPATTERN specified by the "ignore-glob" 216 262 ** is used if the --ignore option is omitted. 263 +** 264 +** Pathnames are displayed according to the "relative-paths" setting, 265 +** unless overridden by the --abs-paths or --rel-paths options. 266 +** 267 +** Options: 268 +** 269 +** --dotfiles Include files with names beginning with "." 270 +** 271 +** --ignore GLOBPATTERN 272 +** Override the "ignore-glob" setting. 273 +** 274 +** --abs-paths Display absolute pathnames. 275 +** 276 +** --rel-paths Display pathnames relative to the current working 277 +** directory. 217 278 */ 218 279 void extra_cmd(void){ 219 280 Blob path; 220 281 Blob repo; 221 282 Stmt q; 222 283 int n; 223 284 const char *zIgnoreFlag = find_option("ignore",0,1); 224 285 int allFlag = find_option("dotfiles",0,0)!=0; 286 + int cwdRelative = 0; 225 287 int outputManifest; 226 288 Glob *pIgnore; 289 + Blob rewrittenPathname; 290 + const char *zPathname, *zDisplayName; 227 291 228 292 db_must_be_within_tree(); 293 + cwdRelative = determine_cwd_relative_option(); 229 294 outputManifest = db_get_boolean("manifest",0); 230 295 db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)"); 231 296 n = strlen(g.zLocalRoot); 232 297 blob_init(&path, g.zLocalRoot, n-1); 233 298 if( zIgnoreFlag==0 ){ 234 299 zIgnoreFlag = db_get("ignore-glob", 0); 235 300 } ................................................................................ 241 306 " WHERE x NOT IN (%s)" 242 307 " ORDER BY 1", 243 308 fossil_all_reserved_names() 244 309 ); 245 310 if( file_tree_name(g.zRepositoryName, &repo, 0) ){ 246 311 db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); 247 312 } 313 + blob_zero(&rewrittenPathname); 248 314 while( db_step(&q)==SQLITE_ROW ){ 249 - fossil_print("%s\n", db_column_text(&q, 0)); 315 + zDisplayName = zPathname = db_column_text(&q, 0); 316 + if( cwdRelative ) { 317 + char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); 318 + file_relative_name(zFullName, &rewrittenPathname); 319 + free(zFullName); 320 + zDisplayName = blob_str(&rewrittenPathname); 321 + if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){ 322 + zDisplayName += 2; /* no unnecessary ./ prefix */ 323 + } 324 + } 325 + fossil_print("%s\n", zDisplayName); 250 326 } 327 + blob_reset(&rewrittenPathname); 251 328 db_finalize(&q); 252 329 } 253 330 254 331 /* 255 332 ** COMMAND: clean 256 333 ** Usage: %fossil clean ?--force? ?--dotfiles? ?--ignore GLOBPATTERN? 257 334 ** ................................................................................ 365 442 if( g.markPrivate ){ 366 443 blob_append(&text, 367 444 "# PRIVATE BRANCH: This check-in will be private and will not sync to\n" 368 445 "# repositories.\n" 369 446 "#\n", -1 370 447 ); 371 448 } 372 - status_report(&text, "# ", 1); 449 + status_report(&text, "# ", 1, 0); 373 450 zEditor = db_get("editor", 0); 374 451 if( zEditor==0 ){ 375 452 zEditor = getenv("VISUAL"); 376 453 } 377 454 if( zEditor==0 ){ 378 455 zEditor = getenv("EDITOR"); 379 456 }
Changes to src/checkout.c.
230 230 } 231 231 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid); 232 232 if( !keepFlag ){ 233 233 vfile_to_disk(vid, 0, 1, promptFlag); 234 234 } 235 235 checkout_set_all_exe(vid); 236 236 manifest_to_disk(vid); 237 + ensure_empty_dirs_created(); 237 238 db_lset_int("checkout", vid); 238 239 undo_reset(); 239 240 db_multi_exec("DELETE FROM vmerge"); 240 241 if( !keepFlag && db_get_boolean("repo-cksum",1) ){ 241 242 vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b); 242 243 vfile_aggregate_checksum_disk(vid, &cksum2); 243 244 if( blob_compare(&cksum1, &cksum2) ){
Changes to src/clone.c.
35 35 ** admin user. This can be overridden using the -A|--admin-user 36 36 ** parameter. 37 37 ** 38 38 ** Options: 39 39 ** 40 40 ** --admin-user|-A USERNAME Make USERNAME the administrator 41 41 ** --private Also clone private branches 42 +** --ssl-identity=filename Use the SSL identity if requested by the server 42 43 ** 43 44 */ 44 45 void clone_cmd(void){ 45 46 char *zPassword; 46 47 const char *zDefaultUser; /* Optional name of the default user */ 47 48 const char *zPw; /* The user clone password */ 48 49 int nErr = 0; ................................................................................ 92 93 db_begin_transaction(); 93 94 db_record_repository_filename(g.argv[3]); 94 95 db_initial_setup(0, zDefaultUser, 0); 95 96 user_select(); 96 97 db_set("content-schema", CONTENT_SCHEMA, 0); 97 98 db_set("aux-schema", AUX_SCHEMA, 0); 98 99 db_set("last-sync-url", g.argv[2], 0); 100 + if( g.zSSLIdentity!=0 ){ 101 + /* If the --ssl-identity option was specified, store it as a setting */ 102 + Blob fn; 103 + blob_zero(&fn); 104 + file_canonical_name(g.zSSLIdentity, &fn); 105 + db_set("ssl-identity", blob_str(&fn), 0); 106 + blob_reset(&fn); 107 + } 99 108 db_multi_exec( 100 109 "REPLACE INTO config(name,value,mtime)" 101 110 " VALUES('server-code', lower(hex(randomblob(20))), now());" 102 111 ); 103 112 url_enable_proxy(0); 104 113 url_get_password_if_needed(); 105 114 g.xlinkClusterOnly = 1;
Changes to src/configure.c.
79 79 { "logo-mimetype", CONFIGSET_SKIN }, 80 80 { "logo-image", CONFIGSET_SKIN }, 81 81 { "project-name", CONFIGSET_PROJ }, 82 82 { "project-description", CONFIGSET_PROJ }, 83 83 { "manifest", CONFIGSET_PROJ }, 84 84 { "ignore-glob", CONFIGSET_PROJ }, 85 85 { "crnl-glob", CONFIGSET_PROJ }, 86 + { "empty-dirs", CONFIGSET_PROJ }, 86 87 { "index-page", CONFIGSET_SKIN }, 87 88 { "timeline-block-markup", CONFIGSET_SKIN }, 88 89 { "timeline-max-comment", CONFIGSET_SKIN }, 89 90 { "ticket-table", CONFIGSET_TKT }, 90 91 { "ticket-common", CONFIGSET_TKT }, 91 92 { "ticket-newpage", CONFIGSET_TKT }, 92 93 { "ticket-viewpage", CONFIGSET_TKT },
Changes to src/db.c.
1397 1397 void db_swap_connections(void){ 1398 1398 if( !g.useAttach ){ 1399 1399 sqlite3 *dbTemp = g.db; 1400 1400 g.db = g.dbConfig; 1401 1401 g.dbConfig = dbTemp; 1402 1402 } 1403 1403 } 1404 + 1405 +/* 1406 +** Logic for reading potentially versioned settings from 1407 +** .fossil-settings/<name> , and emits warnings if necessary. 1408 +** Returns the non-versioned value without modification if there is no 1409 +** versioned value. 1410 +*/ 1411 +static char *db_get_do_versionable(const char *zName, char *zNonVersionedSetting){ 1412 + /* Attempt to load the versioned setting from a checked out file */ 1413 + char *zVersionedSetting = 0; 1414 + int noWarn = 0; 1415 + 1416 + if( db_open_local() ){ 1417 + Blob versionedPathname; 1418 + char *zVersionedPathname; 1419 + blob_zero(&versionedPathname); 1420 + blob_appendf(&versionedPathname, "%s/.fossil-settings/%s", 1421 + g.zLocalRoot, zName); 1422 + zVersionedPathname = blob_str(&versionedPathname); 1423 + if( file_size(zVersionedPathname)>=0 ){ 1424 + /* File exists, and contains the value for this setting. Load from 1425 + ** the file. */ 1426 + Blob setting; 1427 + blob_zero(&setting); 1428 + if( blob_read_from_file(&setting, zVersionedPathname) >= 0 ){ 1429 + blob_trim(&setting); /* Avoid non-obvious problems with line endings 1430 + ** on boolean properties */ 1431 + zVersionedSetting = strdup(blob_str(&setting)); 1432 + } 1433 + blob_reset(&setting); 1434 + /* See if there's a no-warn flag */ 1435 + blob_append(&versionedPathname, ".no-warn", -1); 1436 + if( file_size(blob_str(&versionedPathname))>=0 ){ 1437 + noWarn = 1; 1438 + } 1439 + } 1440 + blob_reset(&versionedPathname); 1441 + } 1442 + /* Display a warning? */ 1443 + if( zVersionedSetting!=0 && zNonVersionedSetting!=0 1444 + && zNonVersionedSetting[0]!='\0' && !noWarn 1445 + ){ 1446 + /* There's a versioned setting, and a non-versioned setting. Tell 1447 + ** the user about the conflict */ 1448 + fossil_warning( 1449 + "setting %s has both versioned and non-versioned values: using " 1450 + "versioned value from file .fossil-settings/%s (to silence this " 1451 + "warning, either create an empty file named " 1452 + ".fossil-settings/%s.no-warn or delete the non-versioned setting " 1453 + " with \"fossil unset %s\")", zName, zName, zName, zName 1454 + ); 1455 + } 1456 + /* Prefer the versioned setting */ 1457 + return ( zVersionedSetting!=0 ) ? zVersionedSetting : zNonVersionedSetting; 1458 +} 1459 + 1404 1460 1405 1461 /* 1406 1462 ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the 1407 1463 ** repository and local databases. 1408 1464 */ 1409 1465 char *db_get(const char *zName, char *zDefault){ 1410 1466 char *z = 0; 1467 + int i; 1468 + const struct stControlSettings *ctrlSetting = 0; 1469 + /* Is this a setting? */ 1470 + for(i=0; ctrlSettings[i].name; i++){ 1471 + if( strcmp(ctrlSettings[i].name, zName)==0 ){ 1472 + ctrlSetting = &(ctrlSettings[i]); 1473 + break; 1474 + } 1475 + } 1411 1476 if( g.repositoryOpen ){ 1412 1477 z = db_text(0, "SELECT value FROM config WHERE name=%Q", zName); 1413 1478 } 1414 1479 if( z==0 && g.configOpen ){ 1415 1480 db_swap_connections(); 1416 1481 z = db_text(0, "SELECT value FROM global_config WHERE name=%Q", zName); 1417 1482 db_swap_connections(); 1483 + } 1484 + if( ctrlSetting!=0 && ctrlSetting->versionable ){ 1485 + /* This is a versionable setting, try and get the info from a checked out file */ 1486 + z = db_get_do_versionable(zName, z); 1418 1487 } 1419 1488 if( z==0 ){ 1420 1489 z = zDefault; 1421 1490 } 1422 1491 return z; 1423 1492 } 1424 1493 void db_set(const char *zName, const char *zValue, int globalFlag){ ................................................................................ 1601 1670 info_cmd(); 1602 1671 } 1603 1672 } 1604 1673 1605 1674 /* 1606 1675 ** Print the value of a setting named zName 1607 1676 */ 1608 -static void print_setting(const char *zName){ 1677 +static void print_setting(const struct stControlSettings *ctrlSetting, int localOpen){ 1609 1678 Stmt q; 1610 1679 if( g.repositoryOpen ){ 1611 1680 db_prepare(&q, 1612 1681 "SELECT '(local)', value FROM config WHERE name=%Q" 1613 1682 " UNION ALL " 1614 1683 "SELECT '(global)', value FROM global_config WHERE name=%Q", 1615 - zName, zName 1684 + ctrlSetting->name, ctrlSetting->name 1616 1685 ); 1617 1686 }else{ 1618 1687 db_prepare(&q, 1619 1688 "SELECT '(global)', value FROM global_config WHERE name=%Q", 1620 - zName 1689 + ctrlSetting->name 1621 1690 ); 1622 1691 } 1623 1692 if( db_step(&q)==SQLITE_ROW ){ 1624 - fossil_print("%-20s %-8s %s\n", zName, db_column_text(&q, 0), 1693 + fossil_print("%-20s %-8s %s\n", ctrlSetting->name, db_column_text(&q, 0), 1625 1694 db_column_text(&q, 1)); 1626 1695 }else{ 1627 - fossil_print("%-20s\n", zName); 1696 + fossil_print("%-20s\n", ctrlSetting->name); 1697 + } 1698 + if( ctrlSetting->versionable && localOpen ){ 1699 + /* Check to see if this is overridden by a versionable settings file */ 1700 + Blob versionedPathname; 1701 + blob_zero(&versionedPathname); 1702 + blob_appendf(&versionedPathname, "%s/.fossil-settings/%s", g.zLocalRoot, ctrlSetting->name); 1703 + if( file_size(blob_str(&versionedPathname))>=0 ){ 1704 + fossil_print(" (overridden by contents of file .fossil-settings/%s)\n", ctrlSetting->name); 1705 + } 1628 1706 } 1629 1707 db_finalize(&q); 1630 1708 } 1631 1709 1632 1710 1633 1711 /* 1634 1712 ** define all settings, which can be controlled via the set/unset ................................................................................ 1640 1718 ** set-commands and displays the 'set'-help as info. 1641 1719 */ 1642 1720 #if INTERFACE 1643 1721 struct stControlSettings { 1644 1722 char const *name; /* Name of the setting */ 1645 1723 char const *var; /* Internal variable name used by db_set() */ 1646 1724 int width; /* Width of display. 0 for boolean values */ 1725 + int versionable; /* Is this setting versionable? */ 1647 1726 char const *def; /* Default value */ 1648 1727 }; 1649 1728 #endif /* INTERFACE */ 1650 1729 struct stControlSettings const ctrlSettings[] = { 1651 - { "access-log", 0, 0, "off" }, 1652 - { "auto-captcha", "autocaptcha", 0, "on" }, 1653 - { "auto-shun", 0, 0, "on" }, 1654 - { "autosync", 0, 0, "on" }, 1655 - { "binary-glob", 0, 32, "" }, 1656 - { "case-sensitive",0, 0, "on" }, 1657 - { "clearsign", 0, 0, "off" }, 1658 - { "crnl-glob", 0, 16, "" }, 1659 - { "default-perms", 0, 16, "u" }, 1660 - { "diff-command", 0, 16, "" }, 1661 - { "dont-push", 0, 0, "off" }, 1662 - { "editor", 0, 16, "" }, 1663 - { "gdiff-command", 0, 16, "gdiff" }, 1664 - { "gmerge-command",0, 40, "" }, 1665 - { "https-login", 0, 0, "off" }, 1666 - { "ignore-glob", 0, 40, "" }, 1667 - { "http-port", 0, 16, "8080" }, 1668 - { "localauth", 0, 0, "off" }, 1669 - { "main-branch", 0, 40, "trunk" }, 1670 - { "manifest", 0, 0, "off" }, 1671 - { "max-upload", 0, 25, "250000" }, 1672 - { "mtime-changes", 0, 0, "on" }, 1673 - { "pgp-command", 0, 32, "gpg --clearsign -o " }, 1674 - { "proxy", 0, 32, "off" }, 1675 - { "repo-cksum", 0, 0, "on" }, 1676 - { "self-register", 0, 0, "off" }, 1677 - { "ssh-command", 0, 32, "" }, 1678 - { "web-browser", 0, 32, "" }, 1679 - { "white-foreground", 0, 0, "off" }, 1680 - { 0,0,0,0 } 1730 + { "access-log", 0, 0, 0, "off" }, 1731 + { "auto-captcha", "autocaptcha", 0, 0, "on" }, 1732 + { "auto-shun", 0, 0, 0, "on" }, 1733 + { "autosync", 0, 0, 0, "on" }, 1734 + { "binary-glob", 0, 32, 1, "" }, 1735 + { "clearsign", 0, 0, 0, "off" }, 1736 + { "case-sensitive",0, 0, 0, "on" }, 1737 + { "crnl-glob", 0, 16, 1, "" }, 1738 + { "default-perms", 0, 16, 0, "u" }, 1739 + { "diff-command", 0, 16, 0, "" }, 1740 + { "dont-push", 0, 0, 0, "off" }, 1741 + { "editor", 0, 16, 0, "" }, 1742 + { "gdiff-command", 0, 16, 0, "gdiff" }, 1743 + { "gmerge-command",0, 40, 0, "" }, 1744 + { "https-login", 0, 0, 0, "off" }, 1745 + { "ignore-glob", 0, 40, 1, "" }, 1746 + { "empty-dirs", 0, 40, 1, "" }, 1747 + { "http-port", 0, 16, 0, "8080" }, 1748 + { "localauth", 0, 0, 0, "off" }, 1749 + { "main-branch", 0, 40, 0, "trunk" }, 1750 + { "manifest", 0, 0, 1, "off" }, 1751 + { "max-upload", 0, 25, 0, "250000" }, 1752 + { "mtime-changes", 0, 0, 0, "on" }, 1753 + { "pgp-command", 0, 32, 0, "gpg --clearsign -o " }, 1754 + { "proxy", 0, 32, 0, "off" }, 1755 + { "relative-paths",0, 0, 0, "on" }, 1756 + { "repo-cksum", 0, 0, 0, "on" }, 1757 + { "self-register", 0, 0, 0, "off" }, 1758 + { "ssl-ca-location",0, 40, 0, "" }, 1759 + { "ssl-identity", 0, 40, 0, "" }, 1760 + { "ssh-command", 0, 32, 0, "" }, 1761 + { "web-browser", 0, 32, 0, "" }, 1762 + { "white-foreground", 0, 0, 0, "off" }, 1763 + { 0,0,0,0,0 } 1681 1764 }; 1682 1765 1683 1766 /* 1684 1767 ** COMMAND: settings 1685 1768 ** COMMAND: unset 1686 1769 ** 1687 1770 ** %fossil settings ?PROPERTY? ?VALUE? ?-global? 1688 1771 ** %fossil unset PROPERTY ?-global? 1689 1772 ** 1690 1773 ** The "settings" command with no arguments lists all properties and their 1691 1774 ** values. With just a property name it shows the value of that property. 1692 1775 ** With a value argument it changes the property for the current repository. 1776 +** 1777 +** Settings marked as versionable are overridden by the contents of the 1778 +** file named .fossil-settings/PROPERTY in the checked out files, if that 1779 +** file exists. 1693 1780 ** 1694 1781 ** The "unset" command clears a property setting. 1695 1782 ** 1696 1783 ** 1697 1784 ** auto-captcha If enabled, the Login page provides a button to 1698 1785 ** fill in the captcha password. Default: on 1699 1786 ** ................................................................................ 1703 1790 ** 1704 1791 ** autosync If enabled, automatically pull prior to commit 1705 1792 ** or update and automatically push after commit or 1706 1793 ** tag or branch creation. If the value is "pullonly" 1707 1794 ** then only pull operations occur automatically. 1708 1795 ** Default: on 1709 1796 ** 1710 -** binary-glob The VALUE is a comma-separated list of GLOB patterns 1711 -** that should be treated as binary files for merging 1712 -** purposes. Example: *.xml 1797 +** binary-glob The VALUE is a comma or newline-separated list of 1798 +** (versionable) GLOB patterns that should be treated as binary files 1799 +** for merging purposes. Example: *.xml 1713 1800 ** 1714 1801 ** case-sensitive If TRUE, the files whose names differ only in case 1715 1802 ** care considered distinct. If FALSE files whose names 1716 1803 ** differ only in case are the same file. Defaults to 1717 1804 ** TRUE for unix and FALSE for windows and mac. 1718 1805 ** 1719 1806 ** clearsign When enabled, fossil will attempt to sign all commits 1720 1807 ** with gpg. When disabled (the default), commits will 1721 1808 ** be unsigned. Default: off 1722 1809 ** 1723 -** crnl-glob A comma-separated list of GLOB patterns for text files 1724 -** in which it is ok to have CR+NL line endings. 1810 +** crnl-glob A comma or newline-separated list of GLOB patterns for 1811 +** (versionable) text files in which it is ok to have CR+NL line endings. 1725 1812 ** Set to "*" to disable CR+NL checking. 1726 1813 ** 1727 1814 ** default-perms Permissions given automatically to new users. For more 1728 1815 ** information on permissions see Users page in Server 1729 1816 ** Administration of the HTTP UI. Default: u. 1730 1817 ** 1731 1818 ** diff-command External command to run when performing a diff. 1732 1819 ** If undefined, the internal text diff will be used. 1733 1820 ** 1734 1821 ** dont-push Prevent this repository from pushing from client to 1735 1822 ** server. Useful when setting up a private branch. 1823 +** 1824 +** empty-dirs A comma or newline-separated list of pathnames. On 1825 +** (versionable) update and checkout commands, if no file or directory 1826 +** exists with that name, an empty directory will be 1827 +** created. 1736 1828 ** 1737 1829 ** editor Text editor command used for check-in comments. 1738 1830 ** 1739 1831 ** gdiff-command External command to run when performing a graphical 1740 1832 ** diff. If undefined, text diff will be used. 1741 1833 ** 1742 1834 ** gmerge-command A graphical merge conflict resolver command operating ................................................................................ 1747 1839 ** 1748 1840 ** http-port The TCP/IP port number to use by the "server" 1749 1841 ** and "ui" commands. Default: 8080 1750 1842 ** 1751 1843 ** https-login Send login creditials using HTTPS instead of HTTP 1752 1844 ** even if the login page request came via HTTP. 1753 1845 ** 1754 -** ignore-glob The VALUE is a comma-separated list of GLOB patterns 1755 -** specifying files that the "extra" command will ignore. 1756 -** Example: *.o,*.obj,*.exe 1846 +** ignore-glob The VALUE is a comma or newline-separated list of GLOB 1847 +** (versionable) patterns specifying files that the "extra" command will 1848 +** ignore. Example: *.o,*.obj,*.exe 1757 1849 ** 1758 1850 ** localauth If enabled, require that HTTP connections from 1759 1851 ** 127.0.0.1 be authenticated by password. If 1760 1852 ** false, all HTTP requests from localhost have 1761 1853 ** unrestricted access to the repository. 1762 1854 ** 1763 1855 ** main-branch The primary branch for the project. Default: trunk 1764 1856 ** 1765 1857 ** manifest If enabled, automatically create files "manifest" and 1766 -** "manifest.uuid" in every checkout. The SQLite and 1858 +** (versionable) "manifest.uuid" in every checkout. The SQLite and 1767 1859 ** Fossil repositories both require this. Default: off. 1768 1860 ** 1769 1861 ** max-upload A limit on the size of uplink HTTP requests. The 1770 1862 ** default is 250000 bytes. 1771 1863 ** 1772 1864 ** mtime-changes Use file modification times (mtimes) to detect when 1773 1865 ** files have been modified. (Default "on".) ................................................................................ 1775 1867 ** pgp-command Command used to clear-sign manifests at check-in. 1776 1868 ** The default is "gpg --clearsign -o ". 1777 1869 ** 1778 1870 ** proxy URL of the HTTP proxy. If undefined or "off" then 1779 1871 ** the "http_proxy" environment variable is consulted. 1780 1872 ** If the http_proxy environment variable is undefined 1781 1873 ** then a direct HTTP connection is used. 1874 +** 1875 +** relative-paths When showing changes and extras, report paths relative 1876 +** to the current working directory. Default: "on" 1782 1877 ** 1783 1878 ** repo-cksum Compute checksums over all files in each checkout 1784 1879 ** as a double-check of correctness. Defaults to "on". 1785 1880 ** Disable on large repositories for a performance 1786 1881 ** improvement. 1787 1882 ** 1788 1883 ** self-register Allow users to register themselves through the HTTP UI. 1789 1884 ** This is useful if you want to see other names than 1790 1885 ** "Anonymous" in e.g. ticketing system. On the other hand 1791 1886 ** users can not be deleted. Default: off. 1887 +** 1888 +** ssl-ca-location The full pathname to a file containing PEM encoded 1889 +** CA root certificates, or a directory of certificates 1890 +** with filenames formed from the certificate hashes as 1891 +** required by OpenSSL. 1892 +** If set, this will override the OS default list of 1893 +** OpenSSL CAs. If unset, the default list will be used. 1894 +** Some platforms may add additional certificates. 1895 +** Check your platform behaviour is as required if the 1896 +** exact contents of the CA root is critical for your 1897 +** application. 1898 +** 1899 +** ssl-identity The full pathname to a file containing a certificate 1900 +** and private key in PEM format. Create by concatenating 1901 +** the certificate and private key files. 1902 +** This identity will be presented to SSL servers to 1903 +** authenticate this client, in addition to the normal 1904 +** password authentication. 1792 1905 ** 1793 1906 ** ssh-command Command used to talk to a remote machine with 1794 1907 ** the "ssh://" protocol. 1795 1908 ** 1796 1909 ** web-browser A shell command used to launch your preferred 1797 1910 ** web browser when given a URL as an argument. 1798 1911 ** Defaults to "start" on windows, "open" on Mac, ................................................................................ 1809 1922 if( !g.repositoryOpen ){ 1810 1923 globalFlag = 1; 1811 1924 } 1812 1925 if( unsetFlag && g.argc!=3 ){ 1813 1926 usage("PROPERTY ?-global?"); 1814 1927 } 1815 1928 if( g.argc==2 ){ 1929 + int openLocal = db_open_local(); 1816 1930 for(i=0; ctrlSettings[i].name; i++){ 1817 - print_setting(ctrlSettings[i].name); 1931 + print_setting(&ctrlSettings[i], openLocal); 1818 1932 } 1819 1933 }else if( g.argc==3 || g.argc==4 ){ 1820 1934 const char *zName = g.argv[2]; 1821 1935 int isManifest; 1822 1936 int n = strlen(zName); 1823 1937 for(i=0; ctrlSettings[i].name; i++){ 1824 1938 if( strncmp(ctrlSettings[i].name, zName, n)==0 ) break; ................................................................................ 1832 1946 } 1833 1947 if( unsetFlag ){ 1834 1948 db_unset(ctrlSettings[i].name, globalFlag); 1835 1949 }else if( g.argc==4 ){ 1836 1950 db_set(ctrlSettings[i].name, g.argv[3], globalFlag); 1837 1951 }else{ 1838 1952 isManifest = 0; 1839 - print_setting(ctrlSettings[i].name); 1953 + print_setting(&ctrlSettings[i], db_open_local()); 1840 1954 } 1841 1955 if( isManifest && g.localOpen ){ 1842 1956 manifest_to_disk(db_lget_int("checkout", 0)); 1843 1957 } 1844 1958 }else{ 1845 1959 usage("?PROPERTY? ?VALUE?"); 1846 1960 }
Changes to src/file.c.
497 497 if( z[i+2]=='/' || z[i+2]==0 ) return 0; 498 498 if( z[i+2]=='.' && (z[i+3]=='/' || z[i+3]==0) ) return 0; 499 499 } 500 500 } 501 501 } 502 502 return 1; 503 503 } 504 + 505 +/* 506 +** Return a pointer to the first character in a pathname past the 507 +** drive letter. This routine is a no-op on unix. 508 +*/ 509 +char *file_without_drive_letter(char *zIn){ 510 +#ifdef _WIN32 511 + if( fossil_isalpha(zIn[0]) && zIn[1]==':' ) zIn += 2; 512 +#endif 513 + return zIn; 514 +} 504 515 505 516 /* 506 517 ** Compute a pathname for a file or directory that is relative 507 518 ** to the current directory. 508 519 */ 509 520 void file_relative_name(const char *zOrigName, Blob *pOut){ 510 521 char *zPath; 511 522 blob_set(pOut, zOrigName); 512 523 blob_resize(pOut, file_simplify_name(blob_buffer(pOut), blob_size(pOut))); 513 - zPath = blob_buffer(pOut); 524 + zPath = file_without_drive_letter(blob_buffer(pOut)); 514 525 if( zPath[0]=='/' ){ 515 526 int i, j; 516 527 Blob tmp; 517 - char zPwd[2000]; 518 - file_getcwd(zPwd, sizeof(zPwd)-20); 519 - for(i=1; zPath[i] && zPwd[i]==zPath[i]; i++){} 528 + char *zPwd; 529 + char zBuf[2000]; 530 + zPwd = zBuf; 531 + file_getcwd(zBuf, sizeof(zBuf)-20); 532 + zPwd = file_without_drive_letter(zBuf); 533 + i = 1; 534 +#ifdef _WIN32 535 + while( zPath[i] && fossil_tolower(zPwd[i])==fossil_tolower(zPath[i]) ) i++; 536 +#else 537 + while( zPath[i] && zPwd[i]==zPath[i] ) i++; 538 +#endif 520 539 if( zPath[i]==0 ){ 521 540 blob_reset(pOut); 522 541 if( zPwd[i]==0 ){ 523 542 blob_append(pOut, ".", 1); 524 543 }else{ 525 544 blob_append(pOut, "..", 2); 526 545 for(j=i+1; zPwd[j]; j++){
Changes to src/glob.c.
108 108 if( zPatternList==0 || zPatternList[0]==0 ) return 0; 109 109 nList = strlen(zPatternList); 110 110 p = fossil_malloc( sizeof(*p) + nList+1 ); 111 111 memset(p, 0, sizeof(*p)); 112 112 z = (char*)&p[1]; 113 113 memcpy(z, zPatternList, nList+1); 114 114 while( z[0] ){ 115 - while( z[0]==',' || z[0]==' ' ) z++; /* Skip leading spaces */ 115 + while( z[0]==',' || z[0]==' ' || z[0]=='\n' || z[0]=='\r' ) z++; /* Skip leading spaces and newlines */ 116 116 if( z[0]=='\'' || z[0]=='"' ){ 117 117 delimiter = z[0]; 118 118 z++; 119 119 }else{ 120 120 delimiter = ','; 121 121 } 122 122 if( z[0]==0 ) break; 123 123 p->azPattern = fossil_realloc(p->azPattern, (p->nPattern+1)*sizeof(char*) ); 124 124 p->azPattern[p->nPattern++] = z; 125 - for(i=0; z[i] && z[i]!=delimiter; i++){} 125 + for(i=0; z[i] && z[i]!=delimiter && z[i]!='\n' && z[i]!='\r'; i++){} 126 126 if( delimiter==',' ){ 127 - /* Remove trailing spaces on a comma-delimited pattern */ 128 - for(j=i; j>1 && z[j-1]==' '; j--){} 127 + /* Remove trailing spaces / newlines on a comma-delimited pattern */ 128 + for(j=i; j>1 && (z[j-1]==' ' || z[j-1]=='\n' || z[j-1]=='\r'); j--){} 129 129 if( j<i ) z[j] = 0; 130 130 } 131 131 if( z[i]==0 ) break; 132 132 z[i] = 0; 133 133 z += i+1; 134 134 } 135 135 return p;
Changes to src/http_ssl.c.
76 76 77 77 /* 78 78 ** Return the current SSL error message 79 79 */ 80 80 const char *ssl_errmsg(void){ 81 81 return sslErrMsg; 82 82 } 83 + 84 +/* 85 +** When a server requests a client certificate that hasn't been provided, 86 +** display a warning message explaining what to do next. 87 +*/ 88 +static int ssl_client_cert_callback(SSL *ssl, X509 **x509, EVP_PKEY **pkey){ 89 + fossil_warning("The remote server requested a client certificate for " 90 + "authentication. Specify the pathname to a file containing the PEM " 91 + "encoded certificate and private key with the --ssl-identity option " 92 + "or the ssl-identity setting."); 93 + return 0; /* no cert available */ 94 +} 83 95 84 96 /* 85 97 ** Call this routine once before any other use of the SSL interface. 86 98 ** This routine does initial configuration of the SSL module. 87 99 */ 88 100 void ssl_global_init(void){ 101 + const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0; 102 + 89 103 if( sslIsInit==0 ){ 90 104 SSL_library_init(); 91 105 SSL_load_error_strings(); 92 106 ERR_load_BIO_strings(); 93 107 OpenSSL_add_all_algorithms(); 94 108 sslCtx = SSL_CTX_new(SSLv23_client_method()); 95 - X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx)); 109 + 110 + /* Set up acceptable CA root certificates */ 111 + zCaSetting = db_get("ssl-ca-location", 0); 112 + if( zCaSetting==0 || zCaSetting[0]=='\0' ){ 113 + /* CA location not specified, use platform's default certificate store */ 114 + X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx)); 115 + }else{ 116 + /* User has specified a CA location, make sure it exists and use it */ 117 + switch( file_isdir(zCaSetting) ){ 118 + case 0: { /* doesn't exist */ 119 + fossil_fatal("ssl-ca-location is set to '%s', " 120 + "but is not a file or directory", zCaSetting); 121 + break; 122 + } 123 + case 1: { /* directory */ 124 + zCaDirectory = zCaSetting; 125 + break; 126 + } 127 + case 2: { /* file */ 128 + zCaFile = zCaSetting; 129 + break; 130 + } 131 + } 132 + if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){ 133 + fossil_fatal("Failed to use CA root certificates from " 134 + "ssl-ca-location '%s'", zCaSetting); 135 + } 136 + } 137 + 138 + /* Load client SSL identity, preferring the filename specified on the command line */ 139 + const char *identityFile = ( g.zSSLIdentity!= 0) ? g.zSSLIdentity : db_get("ssl-identity", 0); 140 + if( identityFile!=0 && identityFile[0]!='\0' ){ 141 + if( SSL_CTX_use_certificate_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!= 1 142 + || SSL_CTX_use_PrivateKey_file(sslCtx, identityFile, SSL_FILETYPE_PEM)!=1 ){ 143 + fossil_fatal("Could not load SSL identity from %s", identityFile); 144 + } 145 + } 146 + /* Register a callback to tell the user what to do when the server asks for a cert */ 147 + SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback); 148 + 96 149 sslIsInit = 1; 97 150 } 98 151 } 99 152 100 153 /* 101 154 ** Call this routine to shutdown the SSL module prior to program exit. 102 155 */ ................................................................................ 202 255 BIO_get_mem_data(mem, &desc); 203 256 204 257 if( hasSavedCertificate ){ 205 258 warning = "WARNING: Certificate doesn't match the " 206 259 "saved certificate for this host!"; 207 260 } 208 261 prompt = mprintf("\nUnknown SSL certificate:\n\n%s\n\n%s\n" 262 + "Either:\n" 263 + " * verify the certificate is correct using the " 264 + "SHA1 fingerprint above\n" 265 + " * use the global ssl-ca-location setting to specify your CA root\n" 266 + " certificates list\n\n" 267 + "If you are not expecting this message, answer no and " 268 + "contact your server\nadministrator.\n\n" 209 269 "Accept certificate [a=always/y/N]? ", desc, warning); 210 270 BIO_free(mem); 211 271 212 272 prompt_user(prompt, &ans); 213 273 free(prompt); 214 274 if( blob_str(&ans)[0]!='y' && blob_str(&ans)[0]!='a' ) { 215 275 X509_free(cert);
Changes to src/main.c.
103 103 char *urlPasswd; /* Password for http: */ 104 104 char *urlCanonical; /* Canonical representation of the URL */ 105 105 char *urlProxyAuth; /* Proxy-Authorizer: string */ 106 106 char *urlFossil; /* The path of the ?fossil=path suffix on ssh: */ 107 107 int dontKeepUrl; /* Do not persist the URL */ 108 108 109 109 const char *zLogin; /* Login name. "" if not logged in. */ 110 + const char *zSSLIdentity; /* Value of --ssl-identity option, filename of SSL client identity */ 110 111 int useLocalauth; /* No login required if from 127.0.0.1 */ 111 112 int noPswd; /* Logged in without password (on 127.0.0.1) */ 112 113 int userUid; /* Integer user id */ 113 114 114 115 /* Information used to populate the RCVFROM table */ 115 116 int rcvid; /* The rcvid. 0 if not yet defined. */ 116 117 char *zIpAddr; /* The remote IP address */ ................................................................................ 249 250 g.fSqlTrace = find_option("sqltrace", 0, 0)!=0; 250 251 g.fSqlStats = find_option("sqlstats", 0, 0)!=0; 251 252 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0; 252 253 if( g.fSqlTrace ) g.fSqlStats = 1; 253 254 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0; 254 255 g.fHttpTrace = find_option("httptrace", 0, 0)!=0; 255 256 g.zLogin = find_option("user", "U", 1); 257 + g.zSSLIdentity = find_option("ssl-identity", 0, 1); 256 258 if( find_option("help",0,0)!=0 ){ 257 259 /* --help anywhere on the command line is translated into 258 260 ** "fossil help argv[1] argv[2]..." */ 259 261 int i; 260 262 char **zNewArgv = fossil_malloc( sizeof(char*)*(g.argc+2) ); 261 263 for(i=1; i<g.argc; i++) zNewArgv[i+1] = argv[i]; 262 264 zNewArgv[i+1] = 0;
Changes to src/setup.c.
1060 1060 @ <table border="0"><tr><td valign="top"> 1061 1061 login_insert_csrf_secret(); 1062 1062 for(pSet=ctrlSettings; pSet->name!=0; pSet++){ 1063 1063 if( pSet->width==0 ){ 1064 1064 onoff_attribute(pSet->name, pSet->name, 1065 1065 pSet->var!=0 ? pSet->var : pSet->name, 1066 1066 is_truth(pSet->def)); 1067 - @ <br /> 1067 + if( pSet->versionable ){ 1068 + @ (v)<br /> 1069 + } else { 1070 + @ <br /> 1071 + } 1068 1072 } 1069 1073 } 1070 1074 @ </td><td style="width: 30;"></td><td valign="top"> 1071 1075 for(pSet=ctrlSettings; pSet->name!=0; pSet++){ 1072 1076 if( pSet->width!=0 ){ 1073 1077 entry_attribute(pSet->name, /*pSet->width*/ 40, pSet->name, 1074 1078 pSet->var!=0 ? pSet->var : pSet->name, 1075 1079 (char*)pSet->def); 1076 - @ <br /> 1080 + if( pSet->versionable ){ 1081 + @ (v)<br /> 1082 + } else { 1083 + @ <br /> 1084 + } 1077 1085 } 1078 1086 } 1079 1087 @ </td></tr></table> 1080 1088 @ <p><input type="submit" name="submit" value="Apply Changes" /></p> 1081 1089 @ </div></form> 1090 + @ <p>Settings marked with (v) are 'versionable' and will be overridden by the contents of files named <tt>.fossil-settings/PROPERTY</tt>.</p> 1082 1091 @ <hr /><p> 1083 1092 @ These settings work in the same way, as the <kbd>set</kbd> commandline:<br /> 1084 1093 @ </p><pre>%s(zHelp_setting_cmd)</pre> 1085 1094 db_end_transaction(0); 1086 1095 style_footer(); 1087 1096 } 1088 1097
Changes to src/update.c.
113 113 if( vid==0 ){ 114 114 fossil_fatal("cannot find current version"); 115 115 } 116 116 if( !nochangeFlag && db_exists("SELECT 1 FROM vmerge") ){ 117 117 fossil_fatal("cannot update an uncommitted merge"); 118 118 } 119 119 if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL); 120 + 121 + /* Create any empty directories now, as well as after the update, so changes in settings are reflected now */ 122 + ensure_empty_dirs_created(); 120 123 121 124 if( internalUpdate ){ 122 125 tid = internalUpdate; 123 126 }else if( g.argc>=3 ){ 124 127 if( fossil_strcmp(g.argv[2], "current")==0 ){ 125 128 /* If VERSION is "current", then use the same algorithm to find the 126 129 ** target as if VERSION were omitted. */ ................................................................................ 439 442 440 443 /* 441 444 ** Clean up the mid and pid VFILE entries. Then commit the changes. 442 445 */ 443 446 if( nochangeFlag ){ 444 447 db_end_transaction(1); /* With --nochange, rollback changes */ 445 448 }else{ 449 + ensure_empty_dirs_created(); 446 450 if( g.argc<=3 ){ 447 451 /* All files updated. Shift the current checkout to the target. */ 448 452 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid); 449 453 checkout_set_all_exe(tid); 450 454 manifest_to_disk(tid); 451 455 db_lset_int("checkout", tid); 452 456 }else{ ................................................................................ 454 458 ** checkout unchanged. */ 455 459 db_multi_exec("DELETE FROM vfile WHERE vid!=%d", vid); 456 460 } 457 461 if( !internalUpdate ) undo_finish(); 458 462 db_end_transaction(0); 459 463 } 460 464 } 465 + 466 +/* 467 +** Make sure empty directories are created 468 +*/ 469 +void ensure_empty_dirs_created(void){ 470 + /* Make empty directories? */ 471 + char *zEmptyDirs = db_get("empty-dirs", 0); 472 + if( zEmptyDirs!=0 ){ 473 + char *bc; 474 + Blob dirName; 475 + Blob dirsList; 476 + 477 + blob_zero(&dirsList); 478 + blob_init(&dirsList, zEmptyDirs, strlen(zEmptyDirs)); 479 + /* Replace commas by spaces */ 480 + bc = blob_str(&dirsList); 481 + while( (*bc)!='\0' ){ 482 + if( (*bc)==',' ) { *bc = ' '; } 483 + ++bc; 484 + } 485 + /* Make directories */ 486 + blob_zero(&dirName); 487 + while( blob_token(&dirsList, &dirName) ){ 488 + const char *zDir = blob_str(&dirName); 489 + /* Make full pathname of the directory */ 490 + Blob path; 491 + const char *zPath; 492 + 493 + blob_zero(&path); 494 + blob_appendf(&path, "%s/%s", g.zLocalRoot, zDir); 495 + zPath = blob_str(&path); 496 + /* Handle various cases of existence of the directory */ 497 + switch( file_isdir(zPath) ){ 498 + case 0: { /* doesn't exist */ 499 + if( file_mkdir(zPath, 0)!=0 ) { 500 + fossil_warning("couldn't create directory %s as " 501 + "required by empty-dirs setting", zDir); 502 + } 503 + break; 504 + } 505 + case 1: { /* exists, and is a directory */ 506 + /* do nothing - required directory exists already */ 507 + break; 508 + } 509 + case 2: { /* exists, but isn't a directory */ 510 + fossil_warning("file %s found, but a directory is required " 511 + "by empty-dirs setting", zDir); 512 + } 513 + } 514 + blob_reset(&path); 515 + } 516 + } 517 +} 461 518 462 519 463 520 /* 464 521 ** Get the contents of a file within the checking "revision". If 465 522 ** revision==NULL then get the file content for the current checkout. 466 523 */ 467 524 int historical_version_of_file(
Changes to www/changes.wiki.
1 1 <title>Change Log</title> 2 2 3 3 <h2>Changes For Version 1.19 (pending)</h2> 4 4 5 5 * Added a ./configure script based on autosetup. 6 6 * Added the "[/help/winsrv | fossil winsrv]" command 7 7 for creating a Fossil service on windows systems. 8 + * Added "versionable settings" where settings that affect 9 + the local tree can be stored in versioned files in the 10 + .fossil-settings directory. 11 + * The status, changes and extras commands now show 12 + pathnames relative to the current working directory, 13 + unless overridden by command line options or the 14 + "relative-paths" setting.<br><b>WARNING:</b> This 15 + change will break scripts which rely on the current 16 + output when the current working directory is not the 17 + repository root. 18 + * Added "empty-dirs" versionable setting. 19 + * Added support for client-side SSL certificates with "ssl-identity" 20 + setting and --ssl-identity option. 21 + * Added "ssl-ca-location" setting to specify trusted root 22 + SSL certificates. 8 23 9 24 <h2>Changes For Version 1.18 (2011-07-14)</h2> 10 25 11 26 * Added this Change Log 12 27 * Added sequential version numbering 13 28 * Added a optional configure script - the Makefile still works for most 14 29 systems.
Changes to www/index.wiki.
125 125 * A tutorial on [./branching.wiki | branching], what it means and how 126 126 to do it using fossil. 127 127 * The [./selfcheck.wiki | automatic self-check] mechanism 128 128 helps insure project integrity. 129 129 * Fossil contains a [./wikitheory.wiki | built-in wiki]. 130 130 * An [./event.wiki | Event] is a special kind of wiki page associated 131 131 with a point in time rather than a name. 132 + * [./settings.wiki | Settings] control the behaviour of fossil. 133 + * [./ssl.wiki | Use SSL] to encrypt communication with the server. 132 134 * There is a 133 135 [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable 134 136 [http://www.mail-archive.com/fossil-users@lists.fossil-scm.org | archives] 135 137 available for discussing fossil issues. 136 138 * [./stats.wiki | Performance statistics] taken from real-world projects 137 139 hosted on fossil. 138 140 * How to [./shunning.wiki | delete content] from a fossil repository.
Changes to www/mkindex.tcl.
7 7 # 8 8 9 9 set doclist { 10 10 bugtheory.wiki {Bug Tracking In Fossil} 11 11 branching.wiki {Branching, Forking, Merging, and Tagging} 12 12 build.wiki {Building and Installing Fossil} 13 13 checkin_names.wiki {Checkin And Version Names} 14 + changes.wiki {Fossil Changelog} 14 15 copyright-release.html {Contributor License Agreement} 15 16 concepts.wiki {Fossil Core Concepts} 16 17 contribute.wiki {Contributing Code or Documentation To The Fossil Project} 17 18 custom_ticket.wiki {Customizing The Ticket System} 18 19 delta_encoder_algorithm.wiki {Fossil Delta Encoding Algorithm} 19 20 delta_format.wiki {Fossil Delta Format} 20 21 embeddeddoc.wiki {Embedded Project Documentation} ................................................................................ 33 34 quickstart.wiki {Fossil Quick Start Guide} 34 35 quotes.wiki 35 36 {Quotes: What People Are Saying About Fossil, Git, and DVCSes in General} 36 37 ../test/release-checklist.wiki {Pre-Release Testing Checklist} 37 38 selfcheck.wiki {Fossil Repository Integrity Self Checks} 38 39 selfhost.wiki {Fossil Self Hosting Repositories} 39 40 server.wiki {How To Configure A Fossil Server} 41 + settings.wiki {Fossil Settings} 40 42 shunning.wiki {Shunning: Deleting Content From Fossil} 41 43 stats.wiki {Performance Statistics} 42 44 style.wiki {Source Code Style Guidelines} 45 + ssl.wiki {Using SSL with Fossil} 43 46 sync.wiki {The Fossil Sync Protocol} 44 47 tech_overview.wiki {A Technical Overview Of The Design And Implementation 45 48 Of Fossil} 46 49 tech_overview.wiki {SQLite Databases Used By Fossil} 47 50 theory1.wiki {Thoughts On The Design Of The Fossil DVCS} 48 51 webui.wiki {The Fossil Web Interface} 49 52 wikitheory.wiki {Wiki In Fossil}
Changes to www/permutedindex.wiki.
9 9 <li><a href="faq.wiki">Asked Questions — Frequently</a></li> 10 10 <li><a href="password.wiki">Authentication — Password Management And</a></li> 11 11 <li><a href="private.wiki">Branches — Creating, Syncing, and Deleting Private</a></li> 12 12 <li><a href="branching.wiki">Branching, Forking, Merging, and Tagging</a></li> 13 13 <li><a href="bugtheory.wiki">Bug Tracking In Fossil</a></li> 14 14 <li><a href="makefile.wiki">Build Process — The Fossil</a></li> 15 15 <li><a href="build.wiki">Building and Installing Fossil</a></li> 16 +<li><a href="changes.wiki">Changelog — Fossil</a></li> 16 17 <li><a href="checkin_names.wiki">Checkin And Version Names</a></li> 17 18 <li><a href="../test/release-checklist.wiki">Checklist — Pre-Release Testing</a></li> 18 19 <li><a href="foss-cklist.wiki">Checklist For Successful Open-Source Projects</a></li> 19 20 <li><a href="selfcheck.wiki">Checks — Fossil Repository Integrity Self</a></li> 20 21 <li><a href="contribute.wiki">Code or Documentation To The Fossil Project — Contributing</a></li> 21 22 <li><a href="style.wiki">Code Style Guidelines — Source</a></li> 22 23 <li><a href="concepts.wiki">Concepts — Fossil Core</a></li> ................................................................................ 42 43 <li><a href="embeddeddoc.wiki">Embedded Project Documentation</a></li> 43 44 <li><a href="delta_encoder_algorithm.wiki">Encoding Algorithm — Fossil Delta</a></li> 44 45 <li><a href="inout.wiki">Export To And From Git — Import And</a></li> 45 46 <li><a href="fileformat.wiki">File Format — Fossil</a></li> 46 47 <li><a href="branching.wiki">Forking, Merging, and Tagging — Branching,</a></li> 47 48 <li><a href="delta_format.wiki">Format — Fossil Delta</a></li> 48 49 <li><a href="fileformat.wiki">Format — Fossil File</a></li> 50 +<li><a href="changes.wiki">Fossil Changelog</a></li> 49 51 <li><a href="concepts.wiki">Fossil Core Concepts</a></li> 50 52 <li><a href="delta_encoder_algorithm.wiki">Fossil Delta Encoding Algorithm</a></li> 51 53 <li><a href="delta_format.wiki">Fossil Delta Format</a></li> 52 54 <li><a href="fileformat.wiki">Fossil File Format</a></li> 53 55 <li><a href="quickstart.wiki">Fossil Quick Start Guide</a></li> 54 56 <li><a href="selfcheck.wiki">Fossil Repository Integrity Self Checks</a></li> 55 57 <li><a href="selfhost.wiki">Fossil Self Hosting Repositories</a></li> 58 +<li><a href="settings.wiki">Fossil Settings</a></li> 56 59 <li><a href="fossil-v-git.wiki">Fossil Versus Git</a></li> 57 60 <li><a href="quotes.wiki">Fossil, Git, and DVCSes in General — Quotes: What People Are Saying About</a></li> 58 61 <li><a href="faq.wiki">Frequently Asked Questions</a></li> 59 62 <li><a href="shunning.wiki">From Fossil — Shunning: Deleting Content</a></li> 60 63 <li><a href="inout.wiki">From Git — Import And Export To And</a></li> 61 64 <li><a href="quotes.wiki">General — Quotes: What People Are Saying About Fossil, Git, and DVCSes in</a></li> 62 65 <li><a href="fossil-v-git.wiki">Git — Fossil Versus</a></li> ................................................................................ 97 100 <li><a href="quotes.wiki">Quotes: What People Are Saying About Fossil, Git, and DVCSes in General</a></li> 98 101 <li><a href="selfhost.wiki">Repositories — Fossil Self Hosting</a></li> 99 102 <li><a href="selfcheck.wiki">Repository Integrity Self Checks — Fossil</a></li> 100 103 <li><a href="quotes.wiki">Saying About Fossil, Git, and DVCSes in General — Quotes: What People Are</a></li> 101 104 <li><a href="selfcheck.wiki">Self Checks — Fossil Repository Integrity</a></li> 102 105 <li><a href="selfhost.wiki">Self Hosting Repositories — Fossil</a></li> 103 106 <li><a href="server.wiki">Server — How To Configure A Fossil</a></li> 107 +<li><a href="settings.wiki">Settings — Fossil</a></li> 104 108 <li><a href="shunning.wiki">Shunning: Deleting Content From Fossil</a></li> 105 109 <li><a href="style.wiki">Source Code Style Guidelines</a></li> 106 110 <li><a href="tech_overview.wiki">SQLite Databases Used By Fossil</a></li> 111 +<li><a href="ssl.wiki">SSL with Fossil — Using</a></li> 107 112 <li><a href="quickstart.wiki">Start Guide — Fossil Quick</a></li> 108 113 <li><a href="stats.wiki">Statistics — Performance</a></li> 109 114 <li><a href="style.wiki">Style Guidelines — Source Code</a></li> 110 115 <li><a href="foss-cklist.wiki">Successful Open-Source Projects — Checklist For</a></li> 111 116 <li><a href="sync.wiki">Sync Protocol — The Fossil</a></li> 112 117 <li><a href="private.wiki">Syncing, and Deleting Private Branches — Creating,</a></li> 113 118 <li><a href="custom_ticket.wiki">System — Customizing The Ticket</a></li> ................................................................................ 116 121 <li><a href="../test/release-checklist.wiki">Testing Checklist — Pre-Release</a></li> 117 122 <li><a href="makefile.wiki">The Fossil Build Process</a></li> 118 123 <li><a href="sync.wiki">The Fossil Sync Protocol</a></li> 119 124 <li><a href="webui.wiki">The Fossil Web Interface</a></li> 120 125 <li><a href="theory1.wiki">Thoughts On The Design Of The Fossil DVCS</a></li> 121 126 <li><a href="custom_ticket.wiki">Ticket System — Customizing The</a></li> 122 127 <li><a href="bugtheory.wiki">Tracking In Fossil — Bug</a></li> 128 +<li><a href="ssl.wiki">Using SSL with Fossil</a></li> 123 129 <li><a href="checkin_names.wiki">Version Names — Checkin And</a></li> 124 130 <li><a href="fossil-v-git.wiki">Versus Git — Fossil</a></li> 125 131 <li><a href="webui.wiki">Web Interface — The Fossil</a></li> 126 132 <li><a href="quotes.wiki">What People Are Saying About Fossil, Git, and DVCSes in General — Quotes:</a></li> 127 133 <li><a href="wikitheory.wiki">Wiki In Fossil</a></li> 134 +<li><a href="ssl.wiki">with Fossil — Using SSL</a></li> 128 135 </ul>
Changes to www/server.wiki.
95 95 </p> 96 96 <p> 97 97 If you are using "inetd" to serve your repository, then you simply need to add "/usr/bin/stunnel" (perhaps on a different path, depending on your setup) before the command line to launch Fossil. 98 98 </p> 99 99 <p> 100 100 At this stage, the standalone server (e.g. "fossil server") does not support SSL. 101 101 </p> 102 +<p> 103 +For more information, see <a href="./ssl.wiki">Using SSL with Fossil</a>. 104 +</p> 102 105 </blockquote> 103 106 104 107 <h2>Various security concerns with hosted repositories</h2><blockquote> 105 108 <p> 106 109 There are two main concerns relating to usage of Fossil for sharing sensitive information (source or any other data): 107 110 <ul> 108 111 <li>Interception of the Fossil synchronization stream, thereby capturing data, and
Added www/settings.wiki.
1 +<title>Fossil Settings</title> 2 + 3 +<h2>Using Fossil Settings</h2> 4 + 5 +Settings control the behaviour of fossil. They are set with the <tt>fossil settings</tt> command, or through the web interface in the Settings page in the Admin section. 6 + 7 +For a list of all settings, view the Settings page, or type <tt>fossil help settings</tt> from the command line. 8 + 9 + 10 +<h3>Repository settings</h3> 11 + 12 +Settings are set on a per-repository basis. When you clone a repository, a subset of settings are copied to your local repository. 13 + 14 +If you make a change to a setting on your local repository, it is not synced back to the server when you <tt>push</tt> or <tt>sync</tt>. If you make a change on the server, you need to manually make the change on all repositories which are cloned from this repository. 15 + 16 +You can also set a setting globally on your local machine. The value will be used for all repositories cloned to your machine, unless overridden explicitly in a particular repository. Global settings can be set by using the <tt>-global</tt> option on the <tt>fossil settings</tt> command. 17 + 18 + 19 +<h3>"Versionable" settings</h3> 20 + 21 +Most of the settings control the behaviour of fossil on your local machine, largely acting to reflect your preference on how you want to use Fossil, how you communicate with the server, or options for hosting a repository on the web. 22 + 23 +However, for historical reasons, some settings affect how you work with versioned files. These are <tt>binary-glob</tt>, <tt>crnl-glob</tt>, <tt>ignore-glob</tt>, <tt>empty-dirs</tt> and <tt>manifest</tt>. The most important is <tt>ignore-glob</tt> which specifies which files should be ignored when looking for unmanaged files with the <tt>extras</tt> command. 24 + 25 +Because these options can change over time, and the inconvenience of replicating changes, these settings are "versionable". As well as being able to be set using the <tt>settings</tt> command or the web interface, you can created versioned files in the <tt>.fossil-settings</tt> directory named with the setting name. The contents of the file is the value of the setting, and these files are checked in, committed, merged, and so on, as with any other file. 26 + 27 +Where a setting is a list of values, such as <tt>ignore-glob</tt>, you can also a newline as a separator as well as a comma. 28 + 29 +For example, to set the list of ignored files, create a <tt>.fossil-settings/ignore-glob</tt> file where each line contains a glob for ignored files. 30 + 31 +If you set the value of a setting using the <tt>settings</tt> command as well as a versioned file, the versioned setting will take precedence. A warning will be displayed.
Added www/ssl.wiki.
1 +<title>SSL and Fossil</title> 2 + 3 +<h2>Using SSL with Fossil</h2> 4 + 5 +If you are storing sensitive information in your repository, you should use SSL to encrypt all communications. This will protect the credentials used to access the server, as well preventing eavesdropping of the contents of your repository. 6 + 7 +To host a repository with SSL, you need to use an web server which supports SSL in front of the Fossil server. You can host it using the CGI option or by proxying Fossil's built in HTTP server. 8 + 9 +Your fossil client must be built with SSL support. The <tt>configure</tt> script will attempt to find OpenSSL on your system, but if necessary, you can specify the location with the <tt>--with-openssl</tt> option. Type <tt>./configure --help</tt> for details. 10 + 11 +Make sure the URL you clone from uses the <tt>https:</tt> scheme to ensure you're using SSL. If your server is configured to serve the repository from http as well as https, it's easy to accidentally use unencrypted HTTP if you forget the all important 's'. 12 + 13 + 14 +<h2>Certificates</h2> 15 + 16 +To verify the identify of a server, SSL uses certificates. Fossil needs to know which certificates you trust. 17 + 18 +If you are using a self-signed certificate, you'll be asked if you want to accept the certificate the first time you communicate with the server. Verify the certificate fingerprint is correct, then answer "always" to remember your decision. 19 + 20 +If you are using a certificate signed by a certificate authority, you need to specify the certificates you trust with the <tt>ssl-ca-location</tt> setting. Set this globally with the <tt>-global</tt> option for convenience. 21 + 22 +This should be set to the location of a file containing all the PEM encoded certificates you trust. You can obtain a certificate using a web browser, for example, Firefox, or just refer to your system's trusted CA roots which are usually stored somewhere in <tt>/etc</tt>. 23 + 24 + 25 +<h2>Client side certificates</h2> 26 + 27 +You can also use client side certificates to add an extra layer of authentication, over and above Fossil's built in user management. If you are particularly paranoid, you'll want to use this to remove the ability of anyone on the internet from making any request to Fossil. Without presenting a valid client side certificate, the web server won't invoke the fossil CGI handler. 28 + 29 +Configure your server to request a client side certificate, and set up a certificate authority to sign your client certificates. For each person who needs to access the repository, create a private key and certificate signed with that CA. 30 + 31 +The PEM encoded private key and certificate should be stored in a single file, simply by concatenating the key and certificate files. Specify the location of this file with the <tt>ssl-identity</tt> setting, or the <tt>--ssl-identity</tt> option to the <tt>clone</tt> command. 32 + 33 +If you've password protected the private key, the password will be requested every time you connect to the server. This password is not stored by fossil, as doing so would defeat the purpose of having a password. 34 + 35 +If you attempt to connect to a server which requests a client certificate, but don't provide one, fossil will show an error message which explains what to do to authenticate with the server. 36 +