예제 #1
0
파일: pkg_repo.c 프로젝트: HonestQiao/pkgng
int
pkg_check_repo_version(struct pkgdb *db, const char *database)
{
	int reposcver;
	int repomajor;
	int ret;

	assert(db != NULL);
	assert(database != NULL);

	if ((ret = get_repo_user_version(db->sqlite, database, &reposcver))
	    != EPKG_OK)
		return (ret);	/* sqlite error */

	/*
	 * If the local pkgng uses a repo schema behind that used to
	 * create the repo, we may still be able use it for reading
	 * (ie pkg install), but pkg repo can't do an incremental
	 * update unless the actual schema matches the compiled in
	 * schema version.
	 *
	 * Use a major - minor version schema: as the user_version
	 * PRAGMA takes an integer version, encode this as MAJOR *
	 * 1000 + MINOR.
	 *
	 * So long as the major versions are the same, the local pkgng
	 * should be compatible with any repo created by a more recent
	 * pkgng
	 */

	/* --- Temporary ---- Grandfather in the old repo schema version
	   so this patch doesn't immediately invalidate all the repos out there */
	if (reposcver == 2)
		reposcver = 2000;
	if (reposcver == 3)
		reposcver = 2001;

	if (reposcver > REPO_SCHEMA_VERSION) {
		pkg_emit_error("Repo %s (schema version %d) is too new - we can"
		    " accept at most version %d", database, reposcver,
		    REPO_SCHEMA_VERSION);
		return (EPKG_REPOSCHEMA);
	}
	
	repomajor = reposcver / 1000;

	if (repomajor < REPO_SCHEMA_MAJOR) {
		pkg_emit_error("Repo %s (schema version %d) is too old - "
		    "need at least schema %d", database, reposcver,
		    REPO_SCHEMA_MAJOR * 1000);
		return (EPKG_REPOSCHEMA);
	}

	return (EPKG_OK);
}
예제 #2
0
파일: pkgdb_repo.c 프로젝트: jillest/pkg
int
pkgdb_repo_open(const char *repodb, bool force, sqlite3 **sqlite,
	bool *incremental)
{
	bool db_not_open;
	int reposcver;
	int retcode = EPKG_OK;

	if (access(repodb, R_OK) == 0)
		*incremental = true;
	else
		*incremental = false;

	sqlite3_initialize();
	db_not_open = true;
	while (db_not_open) {
		if (sqlite3_open(repodb, sqlite) != SQLITE_OK) {
			sqlite3_shutdown();
			return (EPKG_FATAL);
		}

		db_not_open = false;

		/* If the schema is too old, or we're forcing a full
			   update, then we cannot do an incremental update.
			   Delete the existing repo, and promote this to a
			   full update */
		if (!*incremental)
			continue;
		retcode = get_repo_user_version(*sqlite, "main", &reposcver);
		if (retcode != EPKG_OK)
			return (EPKG_FATAL);
		if (force || reposcver != REPO_SCHEMA_VERSION) {
			if (reposcver != REPO_SCHEMA_VERSION)
				pkg_emit_error("re-creating repo to upgrade schema version "
						"from %d to %d", reposcver,
						REPO_SCHEMA_VERSION);
			sqlite3_close(*sqlite);
			unlink(repodb);
			*incremental = false;
			db_not_open = true;
		}
	}

	sqlite3_create_function(*sqlite, "file_exists", 2, SQLITE_ANY, NULL,
	    file_exists, NULL, NULL);

	if (!*incremental) {
		retcode = sql_exec(*sqlite, initsql, REPO_SCHEMA_VERSION);
		if (retcode != EPKG_OK)
			return (retcode);
	}

	return (EPKG_OK);
}
예제 #3
0
파일: pkgdb_repo.c 프로젝트: ppentchev/pkg
int
pkgdb_repo_check_version(struct pkgdb *db, const char *database)
{
    int reposcver;
    int repomajor;
    int ret;

    assert(db != NULL);
    assert(database != NULL);

    if ((ret = get_repo_user_version(db->sqlite, database, &reposcver))
            != EPKG_OK)
        return (ret);	/* sqlite error */

    /*
     * If the local pkgng uses a repo schema behind that used to
     * create the repo, we may still be able use it for reading
     * (ie pkg install), but pkg repo can't do an incremental
     * update unless the actual schema matches the compiled in
     * schema version.
     *
     * Use a major - minor version schema: as the user_version
     * PRAGMA takes an integer version, encode this as MAJOR *
     * 1000 + MINOR.
     *
     * So long as the major versions are the same, the local pkgng
     * should be compatible with any repo created by a more recent
     * pkgng, although it may need some modification of the repo
     * schema
     */

    /* --- Temporary ---- Grandfather in the old repo schema
       version so this patch doesn't immediately invalidate all
       the repos out there */

    if (reposcver == 2)
        reposcver = 2000;
    if (reposcver == 3)
        reposcver = 2001;

    repomajor = reposcver / 1000;

    if (repomajor < REPO_SCHEMA_MAJOR) {
        pkg_emit_error("Repo %s (schema version %d) is too old - "
                       "need at least schema %d", database, reposcver,
                       REPO_SCHEMA_MAJOR * 1000);
        return (EPKG_REPOSCHEMA);
    }

    if (repomajor > REPO_SCHEMA_MAJOR) {
        pkg_emit_error("Repo %s (schema version %d) is too new - "
                       "we can accept at most schema %d", database, reposcver,
                       ((REPO_SCHEMA_MAJOR + 1) * 1000) - 1);
        return (EPKG_REPOSCHEMA);
    }

    /* This is a repo schema version we can work with */

    ret = EPKG_OK;

    if (reposcver < REPO_SCHEMA_VERSION) {
        if (sqlite3_db_readonly(db->sqlite, database)) {
            pkg_emit_error("Repo %s needs schema upgrade from "
                           "%d to %d but it is opened readonly", database,
                           reposcver, REPO_SCHEMA_VERSION
                          );
            ret = EPKG_FATAL;
        } else
            ret = upgrade_repo_schema(db, database, reposcver);
    } else if (reposcver > REPO_SCHEMA_VERSION) {
        if (sqlite3_db_readonly(db->sqlite, database)) {
            pkg_emit_error("Repo %s needs schema downgrade from "
                           "%d to %d but it is opened readonly", database,
                           reposcver, REPO_SCHEMA_VERSION
                          );
            ret = EPKG_FATAL;
        } else
            ret = downgrade_repo_schema(db, database, reposcver);
    }

    return (ret);
}
예제 #4
0
파일: pkg_repo.c 프로젝트: HonestQiao/pkgng
static int
initialize_repo(const char *repodb, bool force, sqlite3 **sqlite)
{
	bool incremental = false;
	bool db_not_open;
	int reposcver;
	int retcode = EPKG_OK;

	const char initsql[] = ""
		"CREATE TABLE packages ("
			"id INTEGER PRIMARY KEY,"
			"origin TEXT UNIQUE,"
			"name TEXT NOT NULL,"
			"version TEXT NOT NULL,"
			"comment TEXT NOT NULL,"
			"desc TEXT NOT NULL,"
			"osversion TEXT,"
			"arch TEXT NOT NULL,"
			"maintainer TEXT NOT NULL,"
			"www TEXT,"
			"prefix TEXT NOT NULL,"
			"pkgsize INTEGER NOT NULL,"
			"flatsize INTEGER NOT NULL,"
			"licenselogic INTEGER NOT NULL,"
			"cksum TEXT NOT NULL,"
			/* relative path to the package in the repository */
			"path TEXT NOT NULL,"
			"pkg_format_version INTEGER"
		");"
		"CREATE TABLE deps ("
			"origin TEXT,"
			"name TEXT,"
			"version TEXT,"
			"package_id INTEGER REFERENCES packages(id)"
		        "  ON DELETE CASCADE ON UPDATE CASCADE,"
			"UNIQUE(package_id, origin)"
		");"
		"CREATE TABLE categories ("
			"id INTEGER PRIMARY KEY, "
			"name TEXT NOT NULL UNIQUE "
		");"
		"CREATE TABLE pkg_categories ("
			"package_id INTEGER REFERENCES packages(id)"
		        "  ON DELETE CASCADE ON UPDATE CASCADE,"
			"category_id INTEGER REFERENCES categories(id)"
			"  ON DELETE RESTRICT ON UPDATE RESTRICT,"
			"UNIQUE(package_id, category_id)"
		");"
		"CREATE TABLE licenses ("
			"id INTEGER PRIMARY KEY,"
			"name TEXT NOT NULL UNIQUE"
		");"
		"CREATE TABLE pkg_licenses ("
			"package_id INTEGER REFERENCES packages(id)"
		        "  ON DELETE CASCADE ON UPDATE CASCADE,"
			"license_id INTEGER REFERENCES licenses(id)"
			"  ON DELETE RESTRICT ON UPDATE RESTRICT,"
			"UNIQUE(package_id, license_id)"
		");"
		"CREATE TABLE options ("
			"package_id INTEGER REFERENCES packages(id)"
		        "  ON DELETE CASCADE ON UPDATE CASCADE,"
			"option TEXT,"
			"value TEXT,"
			"UNIQUE (package_id, option)"
		");"
		"CREATE TABLE shlibs ("
			"id INTEGER PRIMARY KEY,"
			"name TEXT NOT NULL UNIQUE "
		");"
		"CREATE TABLE pkg_shlibs ("
			"package_id INTEGER REFERENCES packages(id)"
		        "  ON DELETE CASCADE ON UPDATE CASCADE,"
			"shlib_id INTEGER REFERENCES shlibs(id)"
			"  ON DELETE RESTRICT ON UPDATE RESTRICT,"
			"UNIQUE(package_id, shlib_id)"
		");"
		"PRAGMA user_version=%d;"
		;

	if (access(repodb, F_OK) == 0)
		incremental = true;

	sqlite3_initialize();
	db_not_open = true;
	while (db_not_open) {
		if (sqlite3_open(repodb, sqlite) != SQLITE_OK) {
			sqlite3_shutdown();
			return (EPKG_FATAL);
		}

		db_not_open = false;

		/* If the schema is too old, or we're forcing a full
		   update, then we cannot do an incremental update.
		   Delete the existing repo, and promote this to a
		   full update */
		if (!incremental)
			continue;
		retcode = get_repo_user_version(*sqlite, "main", &reposcver);
		if (retcode != EPKG_OK)
			return (EPKG_FATAL);
		if (force || reposcver != REPO_SCHEMA_VERSION) {
			if (reposcver != REPO_SCHEMA_VERSION)
				pkg_emit_error("updating repo schema version "
				     "from %d to %d", reposcver,
				     REPO_SCHEMA_VERSION);
			sqlite3_close(*sqlite);
			unlink(repodb);
			incremental = false;
			db_not_open = true;
		}
	}

	sqlite3_create_function(*sqlite, "file_exists", 2, SQLITE_ANY, NULL,
				file_exists, NULL, NULL);

	retcode = sql_exec(*sqlite, "PRAGMA synchronous=off");
	if (retcode != EPKG_OK)
		return (retcode);

	retcode = sql_exec(*sqlite, "PRAGMA journal_mode=memory");
	if (retcode != EPKG_OK)
		return (retcode);

	retcode = sql_exec(*sqlite, "PRAGMA foreign_keys=on");
	if (retcode != EPKG_OK)
		return (retcode);

	if (!incremental) {
		retcode = sql_exec(*sqlite, initsql, REPO_SCHEMA_VERSION);
		if (retcode != EPKG_OK)
			return (retcode);
	}

	retcode = pkgdb_transaction_begin(*sqlite, NULL);
	if (retcode != EPKG_OK)
		return (retcode);

	/* remove anything that is no longer in the repository. */
	if (incremental) {
		const char *obsolete[] = {
			"packages WHERE NOT FILE_EXISTS(path, cksum)",
			"categories WHERE id NOT IN "
				"(SELECT category_id FROM pkg_categories)",
			"licenses WHERE id NOT IN "
				"(SELECT license_id FROM pkg_licenses)",
			"shlibs WHERE id NOT IN "
				"(SELECT shlib_id FROM pkg_shlibs)"
		};
		size_t num_objs = sizeof(obsolete) / sizeof(*obsolete);
		for (size_t obj = 0; obj < num_objs; obj++)
			sql_exec(*sqlite, "DELETE FROM %s;", obsolete[obj]);
	}

	return (EPKG_OK);
}