Merge branch 'fix-974--repo-priorities-and-suggested-vercode' into 'master'

Don't suggest lower versions, despite repository priorities.

Closes #974

See merge request !497
This commit is contained in:
Hans-Christoph Steiner 2017-04-28 08:34:10 +00:00
commit 7199e829f3
2 changed files with 68 additions and 3 deletions

View File

@ -957,12 +957,13 @@ public class AppProvider extends FDroidProvider {
final boolean unstableUpdates = Preferences.get().getUnstableUpdates();
String restrictToStable = unstableUpdates ? "" : (apk + "." + ApkTable.Cols.VERSION_CODE + " <= " + app + "." + Cols.UPSTREAM_VERSION_CODE + " AND ");
String updateSql =
"UPDATE " + app + " SET " + Cols.SUGGESTED_VERSION_CODE + " = ( " +
" SELECT MAX( " + apk + "." + ApkTable.Cols.VERSION_CODE + " ) " +
" FROM " + apk +
" WHERE " +
app + "." + Cols.ROW_ID + " = " + apk + "." + ApkTable.Cols.APP_ID + " AND " +
joinToApksRegardlessOfRepo() + " AND " +
restrictToStable +
" ( " + app + "." + Cols.IS_COMPATIBLE + " = 0 OR " + apk + "." + Cols.IS_COMPATIBLE + " = 1 ) ) " +
" WHERE " + Cols.UPSTREAM_VERSION_CODE + " > 0 ";
@ -970,6 +971,29 @@ public class AppProvider extends FDroidProvider {
db().execSQL(updateSql);
}
/**
* Ensure that when we select a list of {@link ApkTable} rows for which to calculate the
* {@link Cols#SUGGESTED_VERSION_CODE}, that we select all apks belonging to the same package,
* regardless of which repo they come from. We can't just join {@link ApkTable} onto the
* {@link AppMetadataTable}, because the {@link AppMetadataTable} table is specific to a repo.
*
* This is required so that apps always have the highest possible
* {@link Cols#SUGGESTED_VERSION_CODE}, regardless of the repository priorities. Without this,
* then each {@link AppMetadataTable} row will have a different {@link Cols#SUGGESTED_VERSION_CODE}
* depending on which repo it came from. With this, each {@link AppMetadataTable} row has the
* same {@link Cols#SUGGESTED_VERSION_CODE}, even if that version is from a different repo.
*/
private String joinToApksRegardlessOfRepo() {
final String apk = getApkTableName();
final String app = getTableName();
return app + "." + Cols.PACKAGE_ID + " = (" +
" SELECT innerAppName." + Cols.PACKAGE_ID +
" FROM " + app + " as innerAppName " +
" WHERE innerAppName." + Cols.ROW_ID + " = " + apk + "." + ApkTable.Cols.APP_ID +
") ";
}
/**
* We set each app's suggested version to the latest available that is
* compatible, or the latest available if none are compatible.
@ -989,7 +1013,7 @@ public class AppProvider extends FDroidProvider {
" SELECT MAX( " + apk + "." + ApkTable.Cols.VERSION_CODE + " ) " +
" FROM " + apk +
" WHERE " +
app + "." + Cols.ROW_ID + " = " + apk + "." + ApkTable.Cols.APP_ID + " AND " +
joinToApksRegardlessOfRepo() + " AND " +
" ( " + app + "." + Cols.IS_COMPATIBLE + " = 0 OR " + apk + "." + ApkTable.Cols.IS_COMPATIBLE + " = 1 ) ) " +
" WHERE COALESCE(" + Cols.UPSTREAM_VERSION_CODE + ", 0) = 0 OR " + Cols.SUGGESTED_VERSION_CODE + " IS NULL ";

View File

@ -11,6 +11,7 @@ import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.data.ApkProvider;
import org.fdroid.fdroid.data.App;
import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.data.InstalledAppTestUtils;
import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.data.Schema;
@ -20,6 +21,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowSystemProperties;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@ -30,7 +34,7 @@ import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@Config(constants = BuildConfig.class, sdk = 24)
@Config(constants = BuildConfig.class, sdk = 24, shadows = ProperMultiRepoUpdaterTest.ArmSystemProperties.class)
@RunWith(RobolectricTestRunner.class)
public class ProperMultiRepoUpdaterTest extends MultiRepoUpdaterTest {
private static final String TAG = "ProperMultiRepoSupport";
@ -68,6 +72,9 @@ public class ProperMultiRepoUpdaterTest extends MultiRepoUpdaterTest {
assertEmpty();
updateMain();
assertMainRepo();
// Even though there is a version 54 in the repo, version 53 is marked as the current version.
assertCanUpdate("org.adaway", 49, 53);
}
@Test
@ -75,6 +82,8 @@ public class ProperMultiRepoUpdaterTest extends MultiRepoUpdaterTest {
assertEmpty();
updateArchive();
assertMainArchiveRepoMetadata();
assertCanUpdate("org.adaway", 49, 51);
}
@Test
@ -82,6 +91,8 @@ public class ProperMultiRepoUpdaterTest extends MultiRepoUpdaterTest {
assertEmpty();
updateConflicting();
assertConflictingRepo();
assertCanUpdate("org.adaway", 49, 53);
}
private Map<String, App> allApps() {
@ -228,6 +239,17 @@ public class ProperMultiRepoUpdaterTest extends MultiRepoUpdaterTest {
assertMainRepo(repos);
assertMainArchiveRepoMetadata(repos);
assertConflictingRepo(repos);
// Even though there is a version 54 in the repo, version 53 is marked as the current version.
assertCanUpdate("org.adaway", 49, 53);
}
private void assertCanUpdate(String packageName, int installedVersion, int expectedUpdateVersion) {
InstalledAppTestUtils.install(context, packageName, installedVersion, "v" + installedVersion);
List<App> appsToUpdate = AppProvider.Helper.findCanUpdate(context, AppMetadataTable.Cols.ALL);
assertEquals(1, appsToUpdate.size());
assertEquals(installedVersion, appsToUpdate.get(0).installedVersionCode);
assertEquals(expectedUpdateVersion, appsToUpdate.get(0).suggestedVersionCode);
}
private void assertMainRepo() {
@ -386,4 +408,23 @@ public class ProperMultiRepoUpdaterTest extends MultiRepoUpdaterTest {
assertCalendarMetadata(repo, "Conflicting");
}
/**
* Allows us to customize the result of Build.SUPPORTED_ABIS.
* In these tests, we want to "install" and check for updates of Adaway, but that depends
* on the armeabi, x86, or mips architectures, whereas the {@link ShadowSystemProperties}
* only returns armeabi-v7a by default.
* Based on https://groups.google.com/d/msg/robolectric/l_W2EbOek6s/O-GTce8jBQAJ.
*/
@Implements(className = "android.os.SystemProperties")
public static class ArmSystemProperties extends ShadowSystemProperties {
@Implementation
@SuppressWarnings("unused")
public static String get(String key) {
if ("ro.product.cpu.abilist".equals(key)) {
return "armeabi";
}
return ShadowSystemProperties.get(key);
}
}
}