Index: Makefile
==================================================================
--- Makefile
+++ Makefile
@@ -59,16 +59,19 @@
 # You should not need to change anything below this line
 ###############################################################################
 #
 # Automatic platform-specific options.
 HOST_OS!= uname -s
+# Some makes use a different syntax
+HOST_OS_ALT :sh = uname -s
 
 LIB.SunOS= -lsocket -lnsl
 LIB += $(LIB.$(HOST_OS))
+LIB += $(LIB.$(HOST_OS_ALT))
 
 TCC.DragonFly += -DUSE_PREAD
 TCC.FreeBSD += -DUSE_PREAD
 TCC.NetBSD += -DUSE_PREAD
 TCC.OpenBSD += -DUSE_PREAD
 TCC += $(TCC.$(HOST_OS))
 
 include $(SRCDIR)/main.mk

Index: src/add.c
==================================================================
--- src/add.c
+++ src/add.c
@@ -60,11 +60,11 @@
      "manifest.uuid",
   };
 
   if( N>=0 && N<count(azName) ) return azName[N];
   if( N>=count(azName) && N<count(azName)+count(azManifest)
-      && db_get_boolean("manifest",0) ){
+      && db_get_versionable_setting_boolean("manifest",0) ){
     return azManifest[N-count(azName)];
   }
   return 0;
 }
 
@@ -185,11 +185,11 @@
 
   zIgnoreFlag = find_option("ignore",0,1);
   includeDotFiles = find_option("dotfiles",0,0)!=0;
   db_must_be_within_tree();
   if( zIgnoreFlag==0 ){
-    zIgnoreFlag = db_get("ignore-glob", 0);
+    zIgnoreFlag = db_get_versionable_setting("ignore-glob", 0);
   }
   vid = db_lget_int("checkout",0);
   if( vid==0 ){
     fossil_panic("no checkout to add to");
   }
@@ -337,11 +337,11 @@
   int nDelete = 0;
   Glob *pIgnore;
 
   db_must_be_within_tree();
   if( zIgnoreFlag==0 ){
-    zIgnoreFlag = db_get("ignore-glob", 0);
+    zIgnoreFlag = db_get_versionable_setting("ignore-glob", 0);
   }
   vid = db_lget_int("checkout",0);
   if( vid==0 ){
     fossil_panic("no checkout to add to");
   }

Index: src/checkin.c
==================================================================
--- src/checkin.c
+++ src/checkin.c
@@ -224,16 +224,16 @@
   int allFlag = find_option("dotfiles",0,0)!=0;
   int outputManifest;
   Glob *pIgnore;
 
   db_must_be_within_tree();
-  outputManifest = db_get_boolean("manifest",0);
+  outputManifest = db_get_versionable_setting_boolean("manifest",0);
   db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
   n = strlen(g.zLocalRoot);
   blob_init(&path, g.zLocalRoot, n-1);
   if( zIgnoreFlag==0 ){
-    zIgnoreFlag = db_get("ignore-glob", 0);
+    zIgnoreFlag = db_get_versionable_setting("ignore-glob", 0);
   }
   pIgnore = glob_create(zIgnoreFlag);
   vfile_scan(&path, blob_size(&path), allFlag, pIgnore);
   glob_free(pIgnore);
   db_prepare(&q, 
@@ -283,11 +283,11 @@
   allFlag = find_option("force","f",0)!=0;
   dotfilesFlag = find_option("dotfiles",0,0)!=0;
   zIgnoreFlag = find_option("ignore",0,1);
   db_must_be_within_tree();
   if( zIgnoreFlag==0 ){
-    zIgnoreFlag = db_get("ignore-glob", 0);
+    zIgnoreFlag = db_get_versionable_setting("ignore-glob", 0);
   }
   db_multi_exec("CREATE TEMP TABLE sfile(x TEXT PRIMARY KEY)");
   n = strlen(g.zLocalRoot);
   blob_init(&path, g.zLocalRoot, n-1);
   pIgnore = glob_create(zIgnoreFlag);
@@ -831,11 +831,11 @@
   zUserOvrd = find_option("user-override",0,1);
   db_must_be_within_tree();
   noSign = db_get_boolean("omitsign", 0)|noSign;
   if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
   useCksum = db_get_boolean("repo-cksum", 1);
-  outputManifest = db_get_boolean("manifest", 0);
+  outputManifest = db_get_versionable_setting_boolean("manifest", 0);
   verify_all_options();
 
   /* So that older versions of Fossil (that do not understand delta-
   ** manifest) can continue to use this repository, do not create a new
   ** delta-manifest unless this repository already contains one or more
@@ -972,11 +972,11 @@
   ** the identified fils are inserted (if they have been modified).
   */
   db_prepare(&q,
     "SELECT id, %Q || pathname, mrid, %s FROM vfile "
     "WHERE chnged==1 AND NOT deleted AND file_is_selected(id)",
-    g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
+    g.zLocalRoot, glob_expr("pathname", db_get_versionable_setting("crnl-glob",""))
   );
   while( db_step(&q)==SQLITE_ROW ){
     int id, rid;
     const char *zFullname;
     Blob content;

Index: src/checkout.c
==================================================================
--- src/checkout.c
+++ src/checkout.c
@@ -141,11 +141,11 @@
 void manifest_to_disk(int vid){
   char *zManFile;
   Blob manifest;
   Blob hash;
 
-  if( db_get_boolean("manifest",0) ){
+  if( db_get_versionable_setting_boolean("manifest",0) ){
     blob_zero(&manifest);
     content_get(vid, &manifest);
     zManFile = mprintf("%smanifest", g.zLocalRoot);
     blob_write_to_file(&manifest, zManFile);
     free(zManFile);
@@ -242,10 +242,11 @@
   if( !keepFlag ){
     vfile_to_disk(vid, 0, 1, promptFlag);
   }
   checkout_set_all_exe(vid);
   manifest_to_disk(vid);
+  ensure_empty_dirs_created();
   db_lset_int("checkout", vid);
   undo_reset();
   db_multi_exec("DELETE FROM vmerge");
   if( !keepFlag && db_get_boolean("repo-cksum",1) ){
     vfile_aggregate_checksum_manifest(vid, &cksum1, &cksum1b);

Index: src/configure.c
==================================================================
--- src/configure.c
+++ src/configure.c
@@ -81,10 +81,11 @@
   { "project-name",           CONFIGSET_PROJ },
   { "project-description",    CONFIGSET_PROJ },
   { "manifest",               CONFIGSET_PROJ },
   { "ignore-glob",            CONFIGSET_PROJ },
   { "crnl-glob",              CONFIGSET_PROJ },
+  { "empty-dirs",             CONFIGSET_PROJ },
   { "index-page",             CONFIGSET_SKIN },
   { "timeline-block-markup",  CONFIGSET_SKIN },
   { "timeline-max-comment",   CONFIGSET_SKIN },
   { "ticket-table",           CONFIGSET_TKT  },
   { "ticket-common",          CONFIGSET_TKT  },

Index: src/db.c
==================================================================
--- src/db.c
+++ src/db.c
@@ -1390,10 +1390,46 @@
     sqlite3 *dbTemp = g.db;
     g.db = g.dbConfig;
     g.dbConfig = dbTemp;
   }
 }
+
+/*
+** Get a potentially versioned setting - either from .fossil-settings/<name>
+*/
+char *db_get_versionable_setting(const char *zName, char *zDefault){
+  char *s = 0;
+  if( db_open_local() ){
+    /* See if there's a versioned setting */
+    Blob versionedPathname;
+    blob_zero(&versionedPathname);
+    blob_appendf(&versionedPathname, "%s/.fossil-settings/%s", g.zLocalRoot, zName);
+    char *zVersionedPathname = blob_str(&versionedPathname);
+    if( file_size(zVersionedPathname) >= 0 ){
+      /* File exists, and contains the value for this setting. Load from the file. */
+      Blob setting;
+      blob_zero(&setting);
+      if( blob_read_from_file(&setting, zVersionedPathname) >= 0 ){
+        s = strdup(blob_str(&setting));
+      }
+      blob_reset(&setting);
+    }
+    blob_reset(&versionedPathname);
+  }
+  if( s != 0 ){
+    return s;
+  }
+  /* Fall back to settings in the database */
+  return db_get(zName, zDefault);
+}
+int db_get_versionable_setting_boolean(const char *zName, int dflt){
+  char *zVal = db_get_versionable_setting(zName, dflt ? "on" : "off");
+  if( is_truth(zVal) ) return 1;
+  if( is_false(zVal) ) return 0;
+  return dflt;
+}
+
 
 /*
 ** Get and set values from the CONFIG, GLOBAL_CONFIG and VVAR table in the
 ** repository and local databases.
 */
@@ -1652,10 +1688,11 @@
   { "editor",        0,               16, ""                    },
   { "gdiff-command", 0,               16, "gdiff"               },
   { "gmerge-command",0,               40, ""                    },
   { "https-login",   0,                0, "off"                 },
   { "ignore-glob",   0,               40, ""                    },
+  { "empty-dirs",    0,               40, ""                    },
   { "http-port",     0,               16, "8080"                },
   { "localauth",     0,                0, "off"                 },
   { "main-branch",   0,               40, "trunk"               },
   { "manifest",      0,                0, "off"                 },
   { "max-upload",    0,               25, "250000"              },

Index: src/glob.c
==================================================================
--- src/glob.c
+++ src/glob.c
@@ -110,24 +110,24 @@
   p = fossil_malloc( sizeof(*p) + nList+1 );
   memset(p, 0, sizeof(*p));
   z = (char*)&p[1];
   memcpy(z, zPatternList, nList+1);
   while( z[0] ){
-    while( z[0]==',' || z[0]==' ' ) z++;  /* Skip leading spaces */
+    while( z[0]==',' || z[0]==' ' || z[0]=='\n' || z[0]=='\r' ) z++;  /* Skip leading spaces and newlines */
     if( z[0]=='\'' || z[0]=='"' ){
       delimiter = z[0];
       z++;
     }else{
       delimiter = ',';
     }
     if( z[0]==0 ) break;
     p->azPattern = fossil_realloc(p->azPattern, (p->nPattern+1)*sizeof(char*) );
     p->azPattern[p->nPattern++] = z;
-    for(i=0; z[i] && z[i]!=delimiter; i++){}
+    for(i=0; z[i] && z[i]!=delimiter && z[i]!='\n' && z[i]!='\r'; i++){}
     if( delimiter==',' ){
-      /* Remove trailing spaces on a comma-delimited pattern */
-      for(j=i; j>1 && z[j-1]==' '; j--){}
+      /* Remove trailing spaces / newlines on a comma-delimited pattern */
+      for(j=i; j>1 && (z[j-1]==' ' || z[j-1]=='\n' || z[j-1]=='\r'); j--){}
       if( j<i ) z[j] = 0;
     }
     if( z[i]==0 ) break;
     z[i] = 0;
     z += i+1;

Index: src/merge.c
==================================================================
--- src/merge.c
+++ src/merge.c
@@ -91,11 +91,11 @@
   zPivot = find_option("baseline",0,1);
   if( g.argc!=3 ){
     usage("VERSION");
   }
   db_must_be_within_tree();
-  if( zBinGlob==0 ) zBinGlob = db_get("binary-glob",0);
+  if( zBinGlob==0 ) zBinGlob = db_get_versionable_setting("binary-glob",0);
   vid = db_lget_int("checkout", 0);
   if( vid==0 ){
     fossil_fatal("nothing is checked out");
   }
   mid = name_to_rid(g.argv[2]);

Index: src/tar.c
==================================================================
--- src/tar.c
+++ src/tar.c
@@ -215,11 +215,11 @@
   nPrefix = blob_size(&filename);
 
   pManifest = manifest_get(rid, CFTYPE_MANIFEST);
   if( pManifest ){
     mTime = (pManifest->rDate - 2440587.5)*86400.0;
-    if( db_get_boolean("manifest", 0) ){
+    if( db_get_versionable_setting_boolean("manifest", 0) ){
       blob_append(&filename, "manifest", -1);
       zName = blob_str(&filename);
       tar_add_file(zName, &mfile, 0, mTime);
       sha1sum_blob(&mfile, &hash);
       blob_reset(&mfile);

Index: src/update.c
==================================================================
--- src/update.c
+++ src/update.c
@@ -115,10 +115,13 @@
   }
   if( !nochangeFlag && db_exists("SELECT 1 FROM vmerge") ){
     fossil_fatal("cannot update an uncommitted merge");
   }
   if( !nochangeFlag && !internalUpdate ) autosync(AUTOSYNC_PULL);
+  
+  /* Create any empty directories now, as well as after the update, so changes in settings are reflected now */
+  ensure_empty_dirs_created();
 
   if( internalUpdate ){
     tid = internalUpdate;
   }else if( g.argc>=3 ){
     if( strcmp(g.argv[2], "current")==0 ){
@@ -435,10 +438,11 @@
   ** Clean up the mid and pid VFILE entries.  Then commit the changes.
   */
   if( nochangeFlag ){
     db_end_transaction(1);  /* With --nochange, rollback changes */
   }else{
+    ensure_empty_dirs_created();
     if( g.argc<=3 ){
       /* All files updated.  Shift the current checkout to the target. */
       db_multi_exec("DELETE FROM vfile WHERE vid!=%d", tid);
       checkout_set_all_exe(vid);
       manifest_to_disk(tid);
@@ -450,10 +454,35 @@
     }
     if( !internalUpdate ) undo_finish();
     db_end_transaction(0);
   }
 }
+
+/*
+** Make sure empty directories are created
+*/
+void ensure_empty_dirs_created()
+{
+  /* Make empty directories? */
+  char *zEmptyDirs = db_get_versionable_setting("empty-dirs", 0);
+  if( zEmptyDirs!=0 ){
+    Blob dirsList, line;
+    blob_zero(&dirsList);
+    blob_init(&dirsList, zEmptyDirs, strlen(zEmptyDirs));
+    while( blob_line(&dirsList, &line) ){
+      if( blob_buffer(&line)[0]=='#' ) continue;
+      Blob dirName;
+      int l = blob_token(&line, &dirName);
+      if(l > 0) {
+        /* Try and create the directory */
+        if( file_mkdir(blob_str(&dirName), 0)!=0 ) {
+          fossil_warning("couldn't create empty-dir %s", blob_str(&dirName));
+        }
+      }
+    }
+  }
+}
 
 
 /*
 ** Get the contents of a file within the checking "revision".  If
 ** revision==NULL then get the file content for the current checkout.

Index: src/user.c
==================================================================
--- src/user.c
+++ src/user.c
@@ -19,10 +19,14 @@
 ** querying information about users.
 */
 #include "config.h"
 #include "user.h"
 
+#if defined(__sun__) || defined(sun)
+  /* On Solaris, getpass() will only return up to 8 characters. getpassphrase() returns up to 257. */
+  #define getpass getpassphrase
+#endif
 
 /*
 ** Strip leading and trailing space from a string and add the string
 ** onto the end of a blob.
 */

Index: src/zip.c
==================================================================
--- src/zip.c
+++ src/zip.c
@@ -337,11 +337,11 @@
 
   pManifest = manifest_get(rid, CFTYPE_MANIFEST);
   if( pManifest ){
     char *zName;
     zip_set_timedate(pManifest->rDate);
-    if( db_get_boolean("manifest", 0) ){
+    if( db_get_versionable_setting_boolean("manifest", 0) ){
       blob_append(&filename, "manifest", -1);
       zName = blob_str(&filename);
       zip_add_folders(zName);
       zip_add_file(zName, &mfile, 0);
       sha1sum_blob(&mfile, &hash);