From f02f326238fd1e6424bf914e102ce265e7c156ec Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Thu, 6 Aug 2009 16:00:20 +0300 Subject: db: prefer local repositories, and implement --no-network this helps boots sequence when network is not available. --- src/apk.c | 6 +++++- src/apk_database.h | 3 +++ src/apk_defines.h | 1 + src/apk_state.h | 3 ++- src/cache.c | 17 +++++++---------- src/database.c | 45 +++++++++++++++++++++++++++++++++++++-------- src/fetch.c | 16 +++++++--------- src/state.c | 5 +++++ 8 files changed, 67 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/apk.c b/src/apk.c index bbb33fb..6c4acd7 100644 --- a/src/apk.c +++ b/src/apk.c @@ -55,7 +55,8 @@ static struct apk_option generic_options[] = { { 0x107, "keys-dir", "Override directory of trusted keys", required_argument, "KEYSDIR" }, { 0x108, "repositories-file", "Override repositories file", - required_argument, "REPOFILE" } + required_argument, "REPOFILE" }, + { 0x109, "no-network", "Do not use network (cache is still used)" }, }; const char *apk_error_str(int error) @@ -380,6 +381,9 @@ int main(int argc, char **argv) case 0x105: apk_wait = atoi(optarg); break; + case 0x109: + apk_flags |= APK_NO_NETWORK; + break; default: if (applet == NULL || applet->parse == NULL || applet->parse(ctx, &dbopts, r, diff --git a/src/apk_database.h b/src/apk_database.h index 09f9ef7..f2b5ca7 100644 --- a/src/apk_database.h +++ b/src/apk_database.h @@ -98,6 +98,7 @@ struct apk_database { unsigned name_id, num_repos; const char *cache_dir; int permanent; + unsigned int local_repos; struct apk_dependency_array *world; struct apk_string_array *protected_paths; @@ -159,6 +160,8 @@ int apk_db_index_read_file(struct apk_database *db, const char *file, int repo); int apk_db_index_write(struct apk_database *db, struct apk_ostream *os); int apk_db_add_repository(apk_database_t db, apk_blob_t repository); +struct apk_repository *apk_db_select_repo(struct apk_database *db, + struct apk_package *pkg); int apk_repository_update(struct apk_database *db, struct apk_repository *repo); int apk_db_cache_active(struct apk_database *db); diff --git a/src/apk_defines.h b/src/apk_defines.h index 27d4ee4..0ecade4 100644 --- a/src/apk_defines.h +++ b/src/apk_defines.h @@ -63,6 +63,7 @@ extern unsigned int apk_flags; #define APK_PURGE 0x0200 #define APK_INTERACTIVE 0x0400 #define APK_RECURSIVE_DELETE 0x0800 +#define APK_NO_NETWORK 0x1000 #define apk_error(args...) do { apk_log("ERROR: ", args); } while (0) #define apk_warning(args...) do { if (apk_verbosity > 0) { apk_log("WARNING: ", args); } } while (0) diff --git a/src/apk_state.h b/src/apk_state.h index 88a5ad0..72c02b9 100644 --- a/src/apk_state.h +++ b/src/apk_state.h @@ -4,7 +4,7 @@ * Copyright (C) 2008 Timo Teräs * All rights reserved. * - * This program is free software; you can redistribute it and/or modify it + * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. See http://www.gnu.org/ for details. */ @@ -24,6 +24,7 @@ struct apk_change { struct apk_state { unsigned int refs, num_names; + struct apk_database *db; struct list_head change_list_head; apk_name_state_t name[]; }; diff --git a/src/cache.c b/src/cache.c index d4509e1..f9bcb6f 100644 --- a/src/cache.c +++ b/src/cache.c @@ -28,6 +28,7 @@ static int cache_download(struct apk_database *db) struct apk_state *state; struct apk_change *change; struct apk_package *pkg; + struct apk_repository *repo; char item[PATH_MAX], cacheitem[PATH_MAX]; int i, r = 0; @@ -54,17 +55,13 @@ static int cache_download(struct apk_database *db) if (faccessat(db->cache_fd, cacheitem, R_OK, 0) == 0) continue; - for (i = 0; i < db->num_repos; i++) { - if (!(pkg->repos & BIT(i))) - continue; + repo = apk_db_select_repo(db, pkg); + if (repo == NULL) + continue; - apk_pkg_format_plain(pkg, APK_BLOB_BUF(item)); - r = apk_cache_download(db, db->repos[i].url, - item, cacheitem, - APK_SIGN_VERIFY_IDENTITY); - if (r != 0) - return r; - } + apk_pkg_format_plain(pkg, APK_BLOB_BUF(item)); + apk_cache_download(db, repo->url, item, cacheitem, + APK_SIGN_VERIFY_IDENTITY); } err: diff --git a/src/database.c b/src/database.c index ab43ea2..d7bcb2d 100644 --- a/src/database.c +++ b/src/database.c @@ -1156,6 +1156,37 @@ static struct apk_bstream *apk_repository_file_open(struct apk_repository *repo, return apk_bstream_from_url(tmp); } +struct apk_repository *apk_db_select_repo(struct apk_database *db, + struct apk_package *pkg) +{ + unsigned int repos = pkg->repos; + int i; + + /* Always prefer local repositories */ + if ((repos & db->local_repos) != 0) + repos &= db->local_repos; + + /* Pick first repository providing this package */ + for (i = 0; i < APK_MAX_REPOS; i++) + if (repos & BIT(i)) + break; + + if (i >= APK_MAX_REPOS) + return NULL; + + /* If this is a remote repository, and we have no network, + * check that we have it in cache */ + if ((db->local_repos & BIT(i)) == 0 && (apk_flags & APK_NO_NETWORK)) { + char cacheitem[PATH_MAX]; + + apk_pkg_format_cache(pkg, APK_BLOB_BUF(cacheitem)); + if (faccessat(db->cache_fd, cacheitem, R_OK, 0) != 0) + return NULL; + } + + return &db->repos[i]; +} + int apk_repository_update(struct apk_database *db, struct apk_repository *repo) { char cacheitem[PATH_MAX]; @@ -1282,6 +1313,8 @@ int apk_db_add_repository(apk_database_t _db, apk_blob_t repository) targz = 0; } } else { + db->local_repos |= BIT(r); + bs = apk_repository_file_open(repo, apkindex_tar_gz); if (bs == NULL) { bs = apk_repository_file_open(repo, apk_index_gz); @@ -1686,22 +1719,18 @@ static int apk_db_unpack_pkg(struct apk_database *db, struct apk_bstream *bs = NULL; struct apk_istream *tar; char file[PATH_MAX]; - int r, i, need_copy = FALSE; + int r, need_copy = FALSE; if (newpkg->filename == NULL) { struct apk_repository *repo; - for (i = 0; i < APK_MAX_REPOS; i++) - if (newpkg->repos & BIT(i)) - break; - - if (i >= APK_MAX_REPOS) { - apk_error("%s-%s: not present in any repository", + repo = apk_db_select_repo(db, newpkg); + if (repo == NULL) { + apk_error("%s-%s: package is not currently available", newpkg->name->name, newpkg->version); return -1; } - repo = &db->repos[i]; if (apk_db_cache_active(db) && repo->csum.type != APK_CHECKSUM_NONE) { apk_pkg_format_cache(newpkg, APK_BLOB_BUF(file)); diff --git a/src/fetch.c b/src/fetch.c index 9d10f7c..f827d95 100644 --- a/src/fetch.c +++ b/src/fetch.c @@ -95,8 +95,9 @@ static int fetch_package(struct fetch_ctx *fctx, struct apk_package *pkg) { struct apk_istream *is; + struct apk_repository *repo; char pkgfile[PATH_MAX], url[PATH_MAX]; - int r, i, fd; + int r, fd; apk_pkg_format_plain(pkg, APK_BLOB_BUF(pkgfile)); @@ -110,12 +111,9 @@ static int fetch_package(struct fetch_ctx *fctx, } apk_message("Downloading %s-%s", pkg->name->name, pkg->version); - for (i = 0; i < APK_MAX_REPOS; i++) - if (pkg->repos & BIT(i)) - break; - - if (i >= APK_MAX_REPOS) { - apk_error("%s-%s: not present in any repository", + repo = apk_db_select_repo(db, pkg); + if (repo == NULL) { + apk_error("%s-%s: package is not currently available", pkg->name->name, pkg->version); return -1; } @@ -123,8 +121,8 @@ static int fetch_package(struct fetch_ctx *fctx, if (apk_flags & APK_SIMULATE) return 0; - snprintf(url, sizeof(url), "%s%s%s", db->repos[i].url, - db->repos[i].url[strlen(db->repos[i].url)-1] == '/' ? "" : "/", + snprintf(url, sizeof(url), "%s%s%s", repo->url, + repo->url[strlen(repo->url)-1] == '/' ? "" : "/", pkgfile); if (fctx->flags & FETCH_STDOUT) { diff --git a/src/state.c b/src/state.c index ff1a2bb..f18b005 100644 --- a/src/state.c +++ b/src/state.c @@ -142,6 +142,7 @@ struct apk_state *apk_state_new(struct apk_database *db) state = (struct apk_state*) calloc(1, num_bytes); state->refs = 1; state->num_names = db->name_id; + state->db = db; list_init(&state->change_list_head); /* Instantiate each 'name' target in world, and lockout incompatible @@ -292,6 +293,10 @@ int apk_state_lock_dependency(struct apk_state *state, if (apk_pkg_get_state(c->pkgs[i]) == APK_PKG_INSTALLED) installed = pkg; + if (pkg->filename == NULL && + apk_db_select_repo(state->db, pkg) == NULL) + continue; + if (latest == NULL) { latest = pkg; continue; -- cgit v1.2.3-70-g09d2