ensure the canonical repo URL is always included in mirrors list
The mirror logic assumes that it has a mirrors list with at least once valid entry in it. In the index format as defined by `fdroid update`, there is always at least one valid URL: the canonical URL. That also means if there is only one item in the mirrors list, there are no other URLs to try. The initial state of the repos in the database also include the canonical URL in the mirrors list so the mirror logic works on the first index update. That makes it possible to do the first index update via SD Card or USB OTG drive.
This commit is contained in:
parent
9380a6fd0f
commit
ac1a5e0ad8
@ -62,8 +62,10 @@ import java.net.SocketTimeoutException;
|
|||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
@ -284,7 +286,14 @@ public class IndexV1Updater extends IndexUpdater {
|
|||||||
repo.name = getStringRepoValue(repoMap, "name");
|
repo.name = getStringRepoValue(repoMap, "name");
|
||||||
repo.icon = getStringRepoValue(repoMap, "icon");
|
repo.icon = getStringRepoValue(repoMap, "icon");
|
||||||
repo.description = getStringRepoValue(repoMap, "description");
|
repo.description = getStringRepoValue(repoMap, "description");
|
||||||
repo.mirrors = getStringArrayRepoValue(repoMap, "mirrors");
|
|
||||||
|
// ensure the canonical URL is included in the "mirrors" list
|
||||||
|
List<String> mirrorsList = getStringListRepoValue(repoMap, "mirrors");
|
||||||
|
HashSet<String> mirrors = new HashSet<>(mirrorsList.size() + 1);
|
||||||
|
mirrors.addAll(mirrorsList);
|
||||||
|
mirrors.add(repo.address);
|
||||||
|
repo.mirrors = mirrors.toArray(new String[mirrors.size()]);
|
||||||
|
|
||||||
// below are optional, can be default value
|
// below are optional, can be default value
|
||||||
repo.maxage = getIntRepoValue(repoMap, "maxage");
|
repo.maxage = getIntRepoValue(repoMap, "maxage");
|
||||||
repo.version = getIntRepoValue(repoMap, "version");
|
repo.version = getIntRepoValue(repoMap, "version");
|
||||||
@ -372,13 +381,12 @@ public class IndexV1Updater extends IndexUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private String[] getStringArrayRepoValue(Map<String, Object> repoMap, String key) {
|
private List<String> getStringListRepoValue(Map<String, Object> repoMap, String key) {
|
||||||
Object value = repoMap.get(key);
|
Object value = repoMap.get(key);
|
||||||
if (value != null && value instanceof ArrayList) {
|
if (value != null && value instanceof ArrayList) {
|
||||||
ArrayList<String> list = (ArrayList<String>) value;
|
return (List<String>) value;
|
||||||
return list.toArray(new String[list.size()]);
|
|
||||||
}
|
}
|
||||||
return null;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private HashMap<String, Object> parseRepo(ObjectMapper mapper, JsonParser parser) throws IOException {
|
private HashMap<String, Object> parseRepo(ObjectMapper mapper, JsonParser parser) throws IOException {
|
||||||
|
@ -1394,6 +1394,12 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a new repo into the database. This also initializes the list of
|
||||||
|
* "mirror" URLs. There should always be at least one URL there, since the
|
||||||
|
* logic in {@link org.fdroid.fdroid.FDroidApp#getMirror(String, Repo)}
|
||||||
|
* expects at least one entry in the mirrors list.
|
||||||
|
*/
|
||||||
private void insertRepo(SQLiteDatabase db, String name, String address,
|
private void insertRepo(SQLiteDatabase db, String name, String address,
|
||||||
String description, String version, String enabled,
|
String description, String version, String enabled,
|
||||||
String priority, String pushRequests, String pubKey) {
|
String priority, String pushRequests, String pubKey) {
|
||||||
@ -1410,6 +1416,9 @@ public class DBHelper extends SQLiteOpenHelper {
|
|||||||
values.put(RepoTable.Cols.LAST_ETAG, (String) null);
|
values.put(RepoTable.Cols.LAST_ETAG, (String) null);
|
||||||
values.put(RepoTable.Cols.TIMESTAMP, 0);
|
values.put(RepoTable.Cols.TIMESTAMP, 0);
|
||||||
|
|
||||||
|
String[] initializeMirrors = {address};
|
||||||
|
values.put(Schema.RepoTable.Cols.MIRRORS, Utils.serializeCommaSeparatedString(initializeMirrors));
|
||||||
|
|
||||||
switch (pushRequests) {
|
switch (pushRequests) {
|
||||||
case "ignore":
|
case "ignore":
|
||||||
values.put(RepoTable.Cols.PUSH_REQUESTS, Repo.PUSH_REQUEST_IGNORE);
|
values.put(RepoTable.Cols.PUSH_REQUESTS, Repo.PUSH_REQUEST_IGNORE);
|
||||||
|
@ -37,6 +37,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
@ -338,20 +339,29 @@ public class Repo extends ValueObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main repo URL is included in the mirror list, so it only makes
|
||||||
|
* sense to activate this logic if there are more than one entry in the
|
||||||
|
* mirror list.
|
||||||
|
*/
|
||||||
public boolean hasMirrors() {
|
public boolean hasMirrors() {
|
||||||
return (mirrors != null && mirrors.length > 1)
|
return (mirrors != null && mirrors.length > 1)
|
||||||
|| (userMirrors != null && userMirrors.length > 0);
|
|| (userMirrors != null && userMirrors.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link List} of valid URLs to reach this repo, including the canonical URL
|
||||||
|
*/
|
||||||
public List<String> getMirrorList() {
|
public List<String> getMirrorList() {
|
||||||
final ArrayList<String> allMirrors = new ArrayList<String>();
|
final HashSet<String> allMirrors = new HashSet<>();
|
||||||
if (userMirrors != null) {
|
if (userMirrors != null) {
|
||||||
allMirrors.addAll(Arrays.asList(userMirrors));
|
allMirrors.addAll(Arrays.asList(userMirrors));
|
||||||
}
|
}
|
||||||
if (mirrors != null) {
|
if (mirrors != null) {
|
||||||
allMirrors.addAll(Arrays.asList(mirrors));
|
allMirrors.addAll(Arrays.asList(mirrors));
|
||||||
}
|
}
|
||||||
return allMirrors;
|
allMirrors.add(address);
|
||||||
|
return new ArrayList<>(allMirrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -360,19 +370,26 @@ public class Repo extends ValueObject {
|
|||||||
public int getMirrorCount() {
|
public int getMirrorCount() {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (String m : getMirrorList()) {
|
for (String m : getMirrorList()) {
|
||||||
if (!m.equals(address)) {
|
if (FDroidApp.isUsingTor()) {
|
||||||
if (FDroidApp.isUsingTor()) {
|
count++;
|
||||||
count++;
|
} else if (!m.contains(".onion")) {
|
||||||
} else {
|
count++;
|
||||||
if (!m.contains(".onion")) {
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mirror logic assumes that it has a mirrors list with at least once
|
||||||
|
* valid entry in it. In the index format as defined by {@code fdroid update},
|
||||||
|
* there is always at least one valid URL: the canonical URL. That also means
|
||||||
|
* if there is only one item in the mirrors list, there are no other URLs to try.
|
||||||
|
* <p>
|
||||||
|
* The initial state of the repos in the database also include the canonical
|
||||||
|
* URL in the mirrors list so the mirror logic works on the first index
|
||||||
|
* update. That makes it possible to do the first index update via SD Card
|
||||||
|
* or USB OTG drive.
|
||||||
|
*/
|
||||||
public String getMirror(String lastWorkingMirror) {
|
public String getMirror(String lastWorkingMirror) {
|
||||||
if (TextUtils.isEmpty(lastWorkingMirror)) {
|
if (TextUtils.isEmpty(lastWorkingMirror)) {
|
||||||
lastWorkingMirror = address;
|
lastWorkingMirror = address;
|
||||||
@ -382,7 +399,7 @@ public class Repo extends ValueObject {
|
|||||||
if (shuffledMirrors.size() > 1) {
|
if (shuffledMirrors.size() > 1) {
|
||||||
for (String m : shuffledMirrors) {
|
for (String m : shuffledMirrors) {
|
||||||
// Return a non default, and not last used mirror
|
// Return a non default, and not last used mirror
|
||||||
if (!m.equals(address) && !m.equals(lastWorkingMirror)) {
|
if (!m.equals(lastWorkingMirror)) {
|
||||||
if (FDroidApp.isUsingTor()) {
|
if (FDroidApp.isUsingTor()) {
|
||||||
return m;
|
return m;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user