diff --git a/src/org/fdroid/fdroid/DB.java b/src/org/fdroid/fdroid/DB.java index 2f55a8e94..3d1c432ca 100644 --- a/src/org/fdroid/fdroid/DB.java +++ b/src/org/fdroid/fdroid/DB.java @@ -533,53 +533,76 @@ public class DB { return result; } + private static final String[] POPULATE_APP_COLS = new String[] {"description", "webURL", + "trackerURL", "sourceURL", "donateURL" }; + + private void populateAppDetails(App app) { + Cursor cursor = null; + try { + cursor = db.query(TABLE_APP, POPULATE_APP_COLS, "id = ?", + new String[] { app.id }, null, null, null, null); + cursor.moveToFirst(); + app.detail_description = cursor.getString(0); + app.detail_webURL = cursor.getString(1); + app.detail_trackerURL = cursor.getString(2); + app.detail_sourceURL = cursor.getString(3); + app.detail_donateURL = cursor.getString(4); + app.detail_Populated = true; + } catch (Exception e) { + Log.d("FDroid", "Error populating app details " + app.id ); + Log.d("FDroid", e.getMessage()); + } finally { + if (cursor != null) { + cursor.close(); + } + } + } + + private static final String[] POPULATE_APK_COLS = new String[] { "hash", "hashType", "size", "permissions" }; + + private void populateApkDetails(Apk apk, int repo) { + if (repo == 0 || repo == apk.repo) { + Cursor cursor = null; + try { + cursor = db.query( + TABLE_APK, + POPULATE_APK_COLS, + "id = ? and vercode = ?", + new String[] { apk.id, + Integer.toString(apk.vercode) }, null, + null, null, null); + cursor.moveToFirst(); + apk.detail_hash = cursor.getString(0); + apk.detail_hashType = cursor.getString(1); + apk.detail_size = cursor.getInt(2); + apk.detail_permissions = CommaSeparatedList.make(cursor + .getString(3)); + } catch (Exception e) { + Log.d("FDroid", "Error populating apk details for " + apk.id + " (version " + apk.version + ")"); + Log.d("FDroid", e.getMessage()); + } finally { + if (cursor != null) { + cursor.close(); + } + } + } else { + Log.d("FDroid", "Not setting details for apk '" + apk.id + "' (version " + apk.version +") because it belongs to a different repo."); + } + } + // Populate the details for the given app, if necessary. // If 'apkrepo' is non-zero, only apks from that repo are // populated (this is used during the update process) - public void populateDetails(App app, int apkrepo) { - if (app.detail_Populated) - return; - Cursor c = null; - try { - String[] cols = new String[] { "description", "webURL", - "trackerURL", "sourceURL", "donateURL" }; - c = db.query(TABLE_APP, cols, "id = ?", new String[] { app.id }, - null, null, null, null); - c.moveToFirst(); - app.detail_description = c.getString(0); - app.detail_webURL = c.getString(1); - app.detail_trackerURL = c.getString(2); - app.detail_sourceURL = c.getString(3); - app.detail_donateURL = c.getString(4); - c.close(); - c = null; + public void populateDetails(App app, int apkRepo) { + if (!app.detail_Populated) { + populateAppDetails(app); + } - cols = new String[] { "hash", "hashType", "size", "permissions" }; - for (Apk apk : app.apks) { - - if (apkrepo == 0 || apkrepo == apk.repo) { - c = db.query( - TABLE_APK, - cols, - "id = ? and vercode = ?", - new String[] { apk.id, - Integer.toString(apk.vercode) }, null, - null, null, null); - c.moveToFirst(); - apk.detail_hash = c.getString(0); - apk.detail_hashType = c.getString(1); - apk.detail_size = c.getInt(2); - apk.detail_permissions = CommaSeparatedList.make(c - .getString(3)); - c.close(); - c = null; - } + for (Apk apk : app.apks) { + boolean isPopulated = apk.detail_hash != null; + if (!isPopulated) { + populateApkDetails(apk, apkRepo); } - app.detail_Populated = true; - - } finally { - if (c != null) - c.close(); } } @@ -979,6 +1002,7 @@ public class DB { values.put("features", CommaSeparatedList.str(upapk.features)); values.put("compatible", upapk.compatible ? 1 : 0); if (oldapk != null) { + Log.d("FDroid", "Updating apk '" + upapk.id + "' with hash '" + upapk.detail_hash + "'"); db.update(TABLE_APK, values, "id = ? and vercode = " + Integer.toString(oldapk.vercode), new String[] { oldapk.id }); diff --git a/src/org/fdroid/fdroid/UpdateService.java b/src/org/fdroid/fdroid/UpdateService.java index 4b9f44bba..fbf3dacb1 100644 --- a/src/org/fdroid/fdroid/UpdateService.java +++ b/src/org/fdroid/fdroid/UpdateService.java @@ -184,69 +184,124 @@ public class UpdateService extends IntentService implements ProgressListener { List acceptedapps = new ArrayList(); List prevapps = ((FDroidApp) getApplication()).getApps(); - DB db = DB.getDB(); - try { + boolean anyRepoToUpdate = false; + for (DB.Repo repo : repos) { + boolean keepThisRepo = false; + for(int repoId : keeprepos) { + if (repo.id == repoId) { + keepThisRepo = true; + break; + } + } + if (!keepThisRepo) { + anyRepoToUpdate = true; + break; + } + } - // Need to flag things we're keeping despite having received - // no data about during the update. (i.e. stuff from a repo - // that we know is unchanged due to the etag) - for (int keep : keeprepos) { - for (DB.App app : prevapps) { - boolean keepapp = false; - for (DB.Apk apk : app.apks) { - if (apk.repo == keep) { - keepapp = true; - break; - } - } - if (keepapp) { - DB.App app_k = null; - for (DB.App app2 : apps) { - if (app2.id.equals(app.id)) { - app_k = app2; + if (!anyRepoToUpdate) { + Log.d("FDroid", "Not checking app details or compatibility, because all repos were up to date."); + } else { + sendStatus(STATUS_INFO, getString(R.string.status_checking_compatibility)); + List acceptedapps = new ArrayList(); + List prevapps = ((FDroidApp) getApplication()).getApps(); + + DB db = DB.getDB(); + try { + + // Need to flag things we're keeping despite having received + // no data about during the update. (i.e. stuff from a repo + // that we know is unchanged due to the etag) + + // keeep repos are the unchanged ones... + Log.d("FDroid", "Checking " + keeprepos.size() + " unchanged repos."); + for (int keep : keeprepos) { + + // prevapps are all previous apps (and their respective apks + // These *DON'T* yet have the details_hash set)... + Log.d("Fdroid", "Checking '" + keep + "' repo to populate its apk details..."); + for (DB.App app : prevapps) { + boolean keepapp = false; + for (DB.Apk apk : app.apks) { + + // only continue below if the apk is in the sqlite database, + // and belongs to one of the unchanged repos... + + if (apk.repo == keep) { + Log.d("FDroid", "App '" + app.id + "' has apk '" + apk.id + "' which belongs to repo " + keep); + keepapp = true; break; } } - if (app_k == null) { - apps.add(app); - app_k = app; - } - app_k.updated = true; - if (!app_k.detail_Populated) { + if (keepapp) { + DB.App app_k = null; + + // "apps" are the ones found in the index.xml files from + // every index.xml file we came across during update... + // Not that this excludes apps from up-to-date repos (due to etag)... + + Log.d("FDroid", "Searching through apps from index.xml to figure out if they match (the unchanged) '" + app.id + "'..." ); + for (DB.App app2 : apps) { + if (app2.id.equals(app.id)) { + + // "app_k" is the DB.App which is in an index.xml file + // that we downloaded, and also in the database, and in + // a repo which was up to date... I think... + + Log.d("FDroid", "Found matching app '" + app2.id + "' in one of the index.xml files..." ); + app_k = app2; + break; + } + } + + // Just assign it from the "prevapps" - those + // which game straight from sqlite. In this case, + // app_k will *NOT* have hash_details set... + + if (app_k == null) { + + Log.d("FDroid", "Could not find matching app in index.xml files (searched " + apps.size() + " apps). Wlil just assign it from the SQLite version..."); + apps.add(app); + app_k = app; + } + app_k.updated = true; + // At this point, we set the hash_details for each + // of app_k's apks... + Log.d("FDroid", "Populating details for app '" + app_k.id + "' (should set the details_hash for us)..."); db.populateDetails(app_k, keep); + for (DB.Apk apk : app.apks) + if (apk.repo == keep) + apk.updated = true; } - for (DB.Apk apk : app.apks) - if (apk.repo == keep) - apk.updated = true; } } + + prevUpdates = db.beginUpdate(prevapps); + for (DB.App app : apps) { + if (db.updateApplication(app)) + acceptedapps.add(app); + } + db.endUpdate(); + if (notify) + newUpdates = db.getNumUpdates(); + for (DB.Repo repo : repos) + db.writeLastEtag(repo); + } catch (Exception ex) { + db.cancelUpdate(); + Log.e("FDroid", "Exception during update processing:\n" + + Log.getStackTraceString(ex)); + errmsg = "Exception during processing - " + ex.getMessage(); + success = false; + } finally { + DB.releaseDB(); + } + if (success) { + for (DB.App app : acceptedapps) + getIcon(app, repos); + ((FDroidApp) getApplication()).invalidateApps(); } - prevUpdates = db.beginUpdate(prevapps); - for (DB.App app : apps) { - if (db.updateApplication(app)) - acceptedapps.add(app); - } - db.endUpdate(); - if (notify) - newUpdates = db.getNumUpdates(); - for (DB.Repo repo : repos) - db.writeLastEtag(repo); - } catch (Exception ex) { - db.cancelUpdate(); - Log.e("FDroid", "Exception during update processing:\n" - + Log.getStackTraceString(ex)); - errmsg = "Exception during processing - " + ex.getMessage(); - success = false; - } finally { - DB.releaseDB(); } - if (success) { - for (DB.App app : acceptedapps) - getIcon(app, repos); - ((FDroidApp) getApplication()).invalidateApps(); - } - } if (success && changes && notify) {