Merge tag '6.7.2'

pull/848/head
Alex Baker 5 years ago
commit 9b9c8c95a9

@ -1,5 +1,11 @@
Change Log
---
### 6.7.2 (2019-07-08)
* Handle 404 errors when creating new Google Tasks
* Ignore 404 errors when deleting Google Drive files
* Don't report connection errors
### 6.7.1 (2019-07-05)
* Add location chip to task list

@ -25,7 +25,7 @@ android {
defaultConfig {
testApplicationId = "org.tasks.test"
applicationId = "org.tasks"
versionCode = 592
versionCode = 593
versionName = "6.8.0"
targetSdkVersion(Versions.compileSdk)
minSdkVersion(Versions.minSdk)

@ -41,7 +41,7 @@ public class Upgrader {
private static final int V6_0_beta_2 = 523;
private static final int V6_4 = 546;
private static final int V6_7 = 585;
private static final int V6_8 = 592;
private static final int V6_8 = 593;
private final Preferences preferences;
private final Tracker tracker;
private final TagDataDao tagDataDao;

@ -34,10 +34,14 @@ import com.todoroo.astrid.service.TaskDeleter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import javax.net.ssl.SSLException;
import net.fortuna.ical4j.model.property.ProdId;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
@ -102,15 +106,20 @@ public class CaldavSynchronizer {
setError(account, context.getString(R.string.password_required));
return;
}
CaldavClient caldavClient = client.forAccount(account);
List<Response> resources;
try {
resources = caldavClient.getCalendars();
synchronize(account);
} catch (SocketTimeoutException | SSLException | ConnectException | UnknownHostException e) {
Timber.e(e);
account.setError(e.getMessage());
} catch (IOException | DavException e) {
setError(account, e.getMessage());
tracker.reportException(e);
return;
}
}
private void synchronize(CaldavAccount account) throws IOException, DavException {
CaldavClient caldavClient = client.forAccount(account);
List<Response> resources = caldavClient.getCalendars();
Set<String> urls = newHashSet(transform(resources, c -> c.getHref().toString()));
Timber.d("Found calendars: %s", urls);
for (CaldavCalendar calendar :
@ -143,103 +152,98 @@ public class CaldavSynchronizer {
}
}
private void sync(CaldavCalendar caldavCalendar, Response resource, OkHttpClient httpClient) {
private void sync(CaldavCalendar caldavCalendar, Response resource, OkHttpClient httpClient)
throws IOException, DavException {
Timber.d("sync(%s)", caldavCalendar);
HttpUrl httpUrl = resource.getHref();
try {
pushLocalChanges(caldavCalendar, httpClient, httpUrl);
String remoteName = resource.get(DisplayName.class).getDisplayName();
if (!caldavCalendar.getName().equals(remoteName)) {
Timber.d("%s -> %s", caldavCalendar.getName(), remoteName);
caldavCalendar.setName(remoteName);
caldavDao.update(caldavCalendar);
localBroadcastManager.broadcastRefreshList();
}
pushLocalChanges(caldavCalendar, httpClient, httpUrl);
String remoteName = resource.get(DisplayName.class).getDisplayName();
if (!caldavCalendar.getName().equals(remoteName)) {
Timber.d("%s -> %s", caldavCalendar.getName(), remoteName);
caldavCalendar.setName(remoteName);
caldavDao.update(caldavCalendar);
localBroadcastManager.broadcastRefreshList();
}
String remoteCtag = resource.get(GetCTag.class).getCTag();
String localCtag = caldavCalendar.getCtag();
String remoteCtag = resource.get(GetCTag.class).getCTag();
String localCtag = caldavCalendar.getCtag();
if (localCtag != null && localCtag.equals(remoteCtag)) {
Timber.d("%s up to date", caldavCalendar.getName());
return;
}
if (localCtag != null && localCtag.equals(remoteCtag)) {
Timber.d("%s up to date", caldavCalendar.getName());
return;
}
DavCalendar davCalendar = new DavCalendar(httpClient, httpUrl);
ResponseList members = new ResponseList(HrefRelation.MEMBER);
davCalendar.calendarQuery("VTODO", null, null, members);
Set<String> remoteObjects = newHashSet(transform(members, Response::hrefName));
Iterable<Response> changed =
filter(
ImmutableSet.copyOf(members),
vCard -> {
GetETag eTag = vCard.get(GetETag.class);
if (eTag == null || isNullOrEmpty(eTag.getETag())) {
return false;
}
CaldavTask caldavTask = caldavDao.getTask(caldavCalendar.getUuid(), vCard.hrefName());
return caldavTask == null || !eTag.getETag().equals(caldavTask.getEtag());
});
for (List<Response> items : partition(changed, 30)) {
if (items.size() == 1) {
Response vCard = items.get(0);
GetETag eTag = vCard.get(GetETag.class);
HttpUrl url = vCard.getHref();
if (eTag == null || isNullOrEmpty(eTag.getETag())) {
throw new DavException("Received CalDAV GET response without ETag for " + url);
}
Timber.d("SINGLE %s", url);
DavCalendar davCalendar = new DavCalendar(httpClient, httpUrl);
ResponseList members = new ResponseList(HrefRelation.MEMBER);
davCalendar.calendarQuery("VTODO", null, null, members);
Set<String> remoteObjects = newHashSet(transform(members, Response::hrefName));
Iterable<Response> changed =
filter(
ImmutableSet.copyOf(members),
vCard -> {
GetETag eTag = vCard.get(GetETag.class);
if (eTag == null || isNullOrEmpty(eTag.getETag())) {
return false;
}
CaldavTask caldavTask =
caldavDao.getTask(caldavCalendar.getUuid(), vCard.hrefName());
return caldavTask == null || !eTag.getETag().equals(caldavTask.getEtag());
});
for (List<Response> items : partition(changed, 30)) {
if (items.size() == 1) {
Response vCard = items.get(0);
org.tasks.caldav.Response response = new org.tasks.caldav.Response(true);
new DavResource(httpClient, url).get("text/calendar", response);
processVTodo(vCard.hrefName(), caldavCalendar, eTag.getETag(), response.getBody());
} else {
ArrayList<HttpUrl> urls = newArrayList(Iterables.transform(items, Response::getHref));
ResponseList responses = new ResponseList(HrefRelation.MEMBER);
davCalendar.multiget(urls, responses);
Timber.d("MULTI %s", urls);
for (Response vCard : responses) {
GetETag eTag = vCard.get(GetETag.class);
HttpUrl url = vCard.getHref();
if (eTag == null || isNullOrEmpty(eTag.getETag())) {
throw new DavException("Received CalDAV GET response without ETag for " + url);
}
Timber.d("SINGLE %s", url);
org.tasks.caldav.Response response = new org.tasks.caldav.Response(true);
new DavResource(httpClient, url).get("text/calendar", response);
processVTodo(vCard.hrefName(), caldavCalendar, eTag.getETag(), response.getBody());
} else {
ArrayList<HttpUrl> urls = newArrayList(Iterables.transform(items, Response::getHref));
ResponseList responses = new ResponseList(HrefRelation.MEMBER);
davCalendar.multiget(urls, responses);
Timber.d("MULTI %s", urls);
for (Response vCard : responses) {
GetETag eTag = vCard.get(GetETag.class);
HttpUrl url = vCard.getHref();
if (eTag == null || isNullOrEmpty(eTag.getETag())) {
throw new DavException("Received CalDAV GET response without ETag for " + url);
}
CalendarData calendarData = vCard.get(CalendarData.class);
if (calendarData == null || isNullOrEmpty(calendarData.getICalendar())) {
throw new DavException(
"Received CalDAV GET response without CalendarData for " + url);
}
processVTodo(
vCard.hrefName(), caldavCalendar, eTag.getETag(), calendarData.getICalendar());
CalendarData calendarData = vCard.get(CalendarData.class);
if (calendarData == null || isNullOrEmpty(calendarData.getICalendar())) {
throw new DavException("Received CalDAV GET response without CalendarData for " + url);
}
}
}
List<String> deleted =
newArrayList(
difference(
newHashSet(caldavDao.getObjects(caldavCalendar.getUuid())),
newHashSet(remoteObjects)));
if (deleted.size() > 0) {
Timber.d("DELETED %s", deleted);
taskDeleter.delete(caldavDao.getTasks(caldavCalendar.getUuid(), deleted));
processVTodo(
vCard.hrefName(), caldavCalendar, eTag.getETag(), calendarData.getICalendar());
}
}
}
caldavCalendar.setCtag(remoteCtag);
Timber.d("UPDATE %s", caldavCalendar);
caldavDao.update(caldavCalendar);
} catch (Exception e) {
tracker.reportException(e);
List<String> deleted =
newArrayList(
difference(
newHashSet(caldavDao.getObjects(caldavCalendar.getUuid())),
newHashSet(remoteObjects)));
if (deleted.size() > 0) {
Timber.d("DELETED %s", deleted);
taskDeleter.delete(caldavDao.getTasks(caldavCalendar.getUuid(), deleted));
}
caldavCalendar.setCtag(remoteCtag);
Timber.d("UPDATE %s", caldavCalendar);
caldavDao.update(caldavCalendar);
localBroadcastManager.broadcastRefresh();
}

@ -28,11 +28,15 @@ import com.todoroo.astrid.service.TaskCreator;
import com.todoroo.astrid.service.TaskDeleter;
import com.todoroo.astrid.utility.Constants;
import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.inject.Inject;
import javax.net.ssl.SSLException;
import org.tasks.LocalBroadcastManager;
import org.tasks.R;
import org.tasks.analytics.Tracker;
@ -139,6 +143,9 @@ public class GoogleTaskSynchronizer {
} else {
account.setError(context.getString(R.string.requires_pro_subscription));
}
} catch (SocketTimeoutException | SSLException | ConnectException | UnknownHostException e) {
Timber.e(e);
account.setError(e.getMessage());
} catch (UserRecoverableAuthIOException e) {
Timber.e(e);
sendNotification(context, e.getIntent());
@ -322,10 +329,21 @@ public class GoogleTaskSynchronizer {
: null;
String previous =
googleTaskDao.getPrevious(listId, gtasksMetadata.getParent(), gtasksMetadata.getOrder());
Strings.isNullOrEmpty(localParent)
? null
: googleTaskDao.getPrevious(
listId, gtasksMetadata.getParent(), gtasksMetadata.getOrder());
com.google.api.services.tasks.model.Task created =
gtasksInvoker.createGtask(listId, remoteModel, localParent, previous);
com.google.api.services.tasks.model.Task created;
try {
created = gtasksInvoker.createGtask(listId, remoteModel, localParent, previous);
} catch (GoogleJsonResponseException e) {
if (e.getStatusCode() == 404) {
created = gtasksInvoker.createGtask(listId, remoteModel, null, null);
} else {
throw e;
}
}
if (created != null) {
// Update the metadata for the newly created task

@ -12,10 +12,14 @@ import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.services.drive.model.File;
import com.google.common.base.Strings;
import java.io.IOException;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.inject.Inject;
import javax.net.ssl.SSLException;
import org.tasks.R;
import org.tasks.analytics.Tracker;
import org.tasks.drive.DriveInvoker;
@ -23,6 +27,7 @@ import org.tasks.injection.ForApplication;
import org.tasks.injection.InjectingWorker;
import org.tasks.injection.JobComponent;
import org.tasks.preferences.Preferences;
import timber.log.Timber;
public class DriveUploader extends InjectingWorker {
@ -65,11 +70,22 @@ public class DriveUploader extends InjectingWorker {
if (inputData.getBoolean(EXTRA_PURGE, false)) {
List<File> files = drive.getFilesByPrefix(folder.getId(), "auto.");
for (File file : getDeleteList(files)) {
drive.delete(file);
try {
drive.delete(file);
} catch (GoogleJsonResponseException e) {
if (e.getStatusCode() == 404) {
Timber.e(e);
} else {
throw e;
}
}
}
}
return Result.success();
} catch (SocketTimeoutException | SSLException | ConnectException | UnknownHostException e) {
Timber.e(e);
return Result.retry();
} catch (IOException e) {
tracker.reportException(e);
return Result.failure();

Loading…
Cancel
Save