From f9cfa54ff8c9bb44258666d96bc0fd5b65f27f18 Mon Sep 17 00:00:00 2001 From: Terin Stock Date: Mon, 25 Apr 2022 00:17:08 -0700 Subject: init-db: create sqlite database When creating a new repository, create a SQLite3 database in the git directory. This database currently stores objects, refs, and the HEAD pointer. The upstream implementation mixes filesystem and system checks, configuration updating, template copying, and creating the "objects" and "refs" directories. A future revision of this patch should split this logic apart such that the SQLite3 implementation can omit these directories. --- builtin/init-db.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/builtin/init-db.c b/builtin/init-db.c index 546f9c595e..922a514084 100644 --- a/builtin/init-db.c +++ b/builtin/init-db.c @@ -11,6 +11,9 @@ #include "parse-options.h" #include "worktree.h" +#include +#include + #ifndef DEFAULT_GIT_TEMPLATE_DIR #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates" #endif @@ -381,6 +384,18 @@ static void validate_hash_algorithm(struct repository_format *repo_fmt, int hash } } +#if defined(USE_SQLITE) +static char *get_sqlite_dbname(const char *gitdir) +{ + struct strbuf path = STRBUF_INIT; + + strbuf_addstr(&path, gitdir); + strbuf_addstr(&path, "/git.sqlite"); + + return strbuf_detach(&path, NULL); +} +#endif + int init_db(const char *git_dir, const char *real_git_dir, const char *template_dir, int hash, const char *initial_branch, unsigned int flags) @@ -455,6 +470,84 @@ int init_db(const char *git_dir, const char *real_git_dir, git_config_set("receive.denyNonFastforwards", "true"); } +#if defined(USE_SQLITE) + sqlite3 *db; + int rc; + char *errMsg; + char *dbname; + char *ref; + + dbname = get_sqlite_dbname(git_dir); + + rc = sqlite3_open(dbname, &db); + if (rc) { + die(_("can't open database: %s"), sqlite3_errmsg(db)); + } + + // TODO: read sqlite options from gitconfig. + rc = sqlite3_exec(db, "PRAGMA journal_mode = WAL; PRAGMA synchronous = NORMAL; PRAGMA foreign_keys = ON;", NULL, NULL, &errMsg); + if (rc != SQLITE_OK) { + printf(_("SQL Error: %s\n"), errMsg); + sqlite3_free(errMsg); + die("sql error!"); + } + + if (!reinit) { + rc = sqlite3_exec(db, "CREATE TABLE objects(hash BLOB PRIMARY KEY NOT NULL, \ + content BLOB NOT NULL); \ + CREATE TABLE refs(name STRING PRIMARY KEY NOT NULL, \ + hash BLOB NOT NULL, \ + FOREIGN KEY(hash) REFERENCES objects(hash)); \ + CREATE TABLE head(id INTEGER PRIMARY KEY CHECK (id = 0), \ + head BLOB)", NULL, NULL, &errMsg); + if (rc != SQLITE_OK) { + printf(_("SQL Error: %s\n"), errMsg); + sqlite3_free(errMsg); + die("sql error!"); + } + + if (!initial_branch) + initial_branch = git_default_branch_name(flags & INIT_DB_QUIET); + + ref = xstrfmt("refs/heads/%s", initial_branch); + if (check_refname_format(ref, 0) < 0) + die(_("invalid initial branch name: '%s'"), + initial_branch); + + sqlite3_stmt *stmt; + rc = sqlite3_prepare_v2(db, "REPLACE INTO head(id, head) VALUES (0, ?)", -1, &stmt, NULL); + if (rc != SQLITE_OK) { + printf(_("[%d] SQL Error: %s\n"), __LINE__, errMsg); + sqlite3_free(errMsg); + die("sql error!"); + } + + rc = sqlite3_bind_text(stmt, 1, ref, strlen(ref)+1, free); + if (rc != SQLITE_OK) { + printf(_("[%d] SQL Error: %s\n"), __LINE__, errMsg); + sqlite3_free(errMsg); + die("sql error!"); + } + + rc = sqlite3_step(stmt); + if (rc != SQLITE_DONE) { + printf(_("[%d] SQL Error: %s\n"), __LINE__, errMsg); + sqlite3_free(errMsg); + die("sql error!"); + } + + rc = sqlite3_finalize(stmt); + if (rc != SQLITE_OK) { + printf(_("[%d] SQL Error: %s\n"), __LINE__, errMsg); + sqlite3_free(errMsg); + die("sql error!"); + } + } + + sqlite3_close(db); + free(dbname); +#endif + if (!(flags & INIT_DB_QUIET)) { int len = strlen(git_dir); -- cgit 1.4.1