Fossil

Diff
Login

Differences From Artifact [cc2bd11e75]:

To Artifact [d4a81e2726]:


113
114
115
116
117
118
119



120
121
122
123
124
125
126
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129







+
+
+







  int nPrepare;             /* Number of calls to sqlite3_prepare() */
  int nDeleteOnFail;        /* Number of entries in azDeleteOnFail[] */
  struct sCommitHook {
    int (*xHook)(void);         /* Functions to call at db_end_transaction() */
    int sequence;               /* Call functions in sequence order */
  } aHook[5];
  char *azDeleteOnFail[3];  /* Files to delete on a failure */
  char *azBeforeCommit[5];  /* Commands to run prior to COMMIT */
  int nBeforeCommit;        /* Number of entries in azBeforeCommit */
  int nPriorChanges;        /* sqlite3_total_changes() at transaction start */
} db = {0, 0, 0, 0, 0, 0, };

/*
** Arrange for the given file to be deleted on a failure.
*/
void db_delete_on_failure(const char *zFilename){
  assert( db.nDeleteOnFail<count(db.azDeleteOnFail) );
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162
163






164


165
166
167
168
169
170
171
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180
181
182







+










+
+
+
+
+
+
-
+
+







/*
** Begin and end a nested transaction
*/
void db_begin_transaction(void){
  if( db.nBegin==0 ){
    db_multi_exec("BEGIN");
    sqlite3_commit_hook(g.db, db_verify_at_commit, 0);
    db.nPriorChanges = sqlite3_total_changes(g.db);
  }
  db.nBegin++;
}
void db_end_transaction(int rollbackFlag){
  if( g.db==0 ) return;
  if( db.nBegin<=0 ) return;
  if( rollbackFlag ) db.doRollback = 1;
  db.nBegin--;
  if( db.nBegin==0 ){
    int i;
    if( db.doRollback==0 && db.nPriorChanges<sqlite3_total_changes(g.db) ){
      while( db.nBeforeCommit ){
        db.nBeforeCommit--;
        sqlite3_exec(g.db, db.azBeforeCommit[db.nBeforeCommit], 0, 0, 0);
        sqlite3_free(db.azBeforeCommit[db.nBeforeCommit]);
      }
    if( db.doRollback==0 ) leaf_do_pending_checks();
      leaf_do_pending_checks();
    }
    for(i=0; db.doRollback==0 && i<db.nCommitHook; i++){
      db.doRollback |= db.aHook[i].xHook();
    }
    while( db.pAllStmt ){
      db_finalize(db.pAllStmt);
    }
    db_multi_exec(db.doRollback ? "ROLLBACK" : "COMMIT");
485
486
487
488
489
490
491














492
493
494
495
496
497
498
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523







+
+
+
+
+
+
+
+
+
+
+
+
+
+







  rc = sqlite3_exec(g.db, blob_buffer(&sql), 0, 0, &zErr);
  if( rc!=SQLITE_OK ){
    db_err("%s\n%s", zErr, blob_buffer(&sql));
  }
  blob_reset(&sql);
  return rc;
}

/*
** Optionally make the following changes to the database if feasible and
** convenient.  Do not start a transaction for these changes, but only
** make these changes if other changes are also being made.
*/
void db_optional_sql(const char *zDb, const char *zSql, ...){
  if( db_is_writeable(zDb) && db.nBeforeCommit < count(db.azBeforeCommit) ){
    va_list ap;
    va_start(ap, zSql);
    db.azBeforeCommit[db.nBeforeCommit++] = sqlite3_vmprintf(zSql, ap);
    va_end(ap);
  }
}

/*
** Execute a query and return a single integer value.
*/
i64 db_int64(i64 iDflt, const char *zSql, ...){
  va_list ap;
  Stmt s;
1005
1006
1007
1008
1009
1010
1011







1012
1013
1014
1015
1016
1017
1018
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050







+
+
+
+
+
+
+







** Return TRUE if the schema is out-of-date
*/
int db_schema_is_outofdate(void){
  return db_exists("SELECT 1 FROM config"
                   " WHERE name='aux-schema'"
                   "   AND value<>'%s'", AUX_SCHEMA);
}

/*
** Return true if the database is writeable
*/
int db_is_writeable(const char *zName){
  return !sqlite3_db_readonly(g.db, db_name(zName));
}

/*
** Verify that the repository schema is correct.  If it is not correct,
** issue a fatal error and die.
*/
void db_verify_schema(void){
  if( db_schema_is_outofdate() ){
1059
1060
1061
1062
1063
1064
1065
1066

1067
1068
1069
1070
1071
1072
1073
1091
1092
1093
1094
1095
1096
1097

1098
1099
1100
1101
1102
1103
1104
1105







-
+









/*
** Open the local database.  If unable, exit with an error.
*/
void db_must_be_within_tree(void){
  if( db_open_local()==0 ){
    fossil_fatal("not within an open checkout");
    fossil_fatal("current directory is not within an open checkout");
  }
  db_open_repository(0);
  db_verify_schema();
}

/*
** Close the database connection.
1721
1722
1723
1724
1725
1726
1727






1728
1729
1730



1731
1732
1733
1734
1735
1736
1737
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766


1767
1768
1769
1770
1771
1772
1773
1774
1775
1776







+
+
+
+
+
+

-
-
+
+
+







    Blob localRoot;
    file_canonical_name(g.zLocalRoot, &localRoot, 1);
    db_multi_exec(
      "REPLACE INTO global_config(name, value)"
      "VALUES('ckout:%q','%q');",
      blob_str(&localRoot), blob_str(&full)
    );
    db_swap_connections();
    db_optional_sql("repository", 
        "REPLACE INTO config(name,value,mtime)"
        "VALUES('ckout:%q',1,now())",
        blob_str(&localRoot)
    );
    blob_reset(&localRoot);
  }
  db_swap_connections();
  }else{
    db_swap_connections();
  }
  blob_reset(&full);
}

/*
** COMMAND: open
**
** Usage: %fossil open FILENAME ?VERSION? ?OPTIONS?
1762
1763
1764
1765
1766
1767
1768





1769
1770


1771
1772
1773
1774
1775
1776
1777
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812


1813
1814
1815
1816
1817
1818
1819
1820
1821







+
+
+
+
+
-
-
+
+







    usage("REPOSITORY-FILENAME ?VERSION?");
  }
  if( !allowNested && db_open_local() ){
    fossil_panic("already within an open tree rooted at %s", g.zLocalRoot);
  }
  file_canonical_name(g.argv[2], &path, 0);
  db_open_repository(blob_str(&path));
#if defined(_WIN32)
# define LOCALDB_NAME "./_FOSSIL_"
#else
# define LOCALDB_NAME "./.fslckout"
#endif
  db_init_database("./_FOSSIL_", zLocalSchema, (char*)0);
  db_delete_on_failure("./_FOSSIL_");
  db_init_database(LOCALDB_NAME, zLocalSchema, (char*)0);
  db_delete_on_failure(LOCALDB_NAME);
  db_open_local();
  db_lset("repository", g.argv[2]);
  db_record_repository_filename(blob_str(&path));
  vid = db_int(0, "SELECT pid FROM plink y"
                  " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)");
  if( vid==0 ){
    db_lset_int("checkout", 1);
1851
1852
1853
1854
1855
1856
1857

1858
1859
1860
1861
1862
1863
1864
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909







+







  char const *def;      /* Default value */
};
#endif /* INTERFACE */
struct stControlSettings const ctrlSettings[] = {
  { "access-log",    0,                0, 0, "off"                 },
  { "allow-symlinks",0,                0, 1, "off"                 },
  { "auto-captcha",  "autocaptcha",    0, 0, "on"                  },
  { "auto-hyperlink",0,                0, 0, "on",                 },
  { "auto-shun",     0,                0, 0, "on"                  },
  { "autosync",      0,                0, 0, "on"                  },
  { "binary-glob",   0,               32, 1, ""                    },
  { "clearsign",     0,                0, 0, "off"                 },
  { "case-sensitive",0,                0, 0, "on"                  },
  { "crnl-glob",     0,               16, 1, ""                    },
  { "default-perms", 0,               16, 0, "u"                   },
1915
1916
1917
1918
1919
1920
1921





1922
1923
1924
1925
1926
1927
1928
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978







+
+
+
+
+







**                     (existing links in repository created on Unix become 
**                     plain-text files with link destination path inside).
**                     Default: off
**
**    auto-captcha     If enabled, the Login page provides a button to
**                     fill in the captcha password.  Default: on
**
**    auto-hyperlink   Use javascript to enable hyperlinks on web pages
**                     for all users (regardless of the "h" privilege) if the
**                     User-Agent string in the HTTP header look like it came
**                     from real person, not a spider or bot.  Default: on
**
**    auto-shun        If enabled, automatically pull the shunning list
**                     from a server to which the client autosyncs.
**                     Default: on
**
**    autosync         If enabled, automatically pull prior to commit
**                     or update and automatically push after commit or
**                     tag or branch creation.  If the value is "pullonly"